>[success] # Leetcode -- 1370上升下降字符串
* 题目描述
给你一个字符串 s ,请你根据下面的算法重新构造字符串:
从 s 中选出 最小 的字符,将它 接在 结果字符串的后面。
从 s 剩余字符中选出 最小 的字符,且该字符比上一个添加的字符大,将它 接在 结果字符串后面。
重复步骤 2 ,直到你没法从 s 中选择字符。
从 s 中选出 最大 的字符,将它 接在 结果字符串的后面。
从 s 剩余字符中选出 最大 的字符,且该字符比上一个添加的字符小,将它 接在 结果字符串后面。
重复步骤 5 ,直到你没法从 s 中选择字符。
重复步骤 1 到 6 ,直到 s 中所有字符都已经被选过。
在任何一步中,如果最小或者最大字符不止一个 ,你可以选择其中任意一个,并将其添加到结果字符串。
请你返回将 s 中字符重新排序后的 结果字符串 。
* 示例 1:
~~~
输入:s = "aaaabbbbcccc"
输出:"abccbaabccba"
解释:第一轮的步骤 1,2,3 后,结果字符串为 result = "abc"
第一轮的步骤 4,5,6 后,结果字符串为 result = "abccba"
第一轮结束,现在 s = "aabbcc" ,我们再次回到步骤 1
第二轮的步骤 1,2,3 后,结果字符串为 result = "abccbaabc"
第二轮的步骤 4,5,6 后,结果字符串为 result = "abccbaabccba"
~~~
* 示例 2:
~~~
输入:s = "rat"
输出:"art"
解释:单词 "rat" 在上述算法重排序以后变成 "art"
~~~
* 示例 3:
~~~
输入:s = "leetcode"
输出:"cdelotee"
~~~
* 示例 4:
~~~
输入:s = "ggggggg"
输出:"ggggggg"
~~~
* 示例 5:
~~~
输入:s = "spo"
输出:"ops"
~~~
* 提示:
~~~
1 <= s.length <= 500
s 只包含小写英文字母。
~~~
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/increasing-decreasing-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
>[danger] ##### 简单概括
先将字符串中不重复的每一项**先升序排列**在**降序排列依**次交替组成新字符串
>[info] ## 题解
题目中提到字符串是由**小写字母**组成,因此可以利用**ascii** 映射数组脚标思路来做字母存储,因为在数组中存储后,每个字母此时已经是按照升序排序好,因此只要**正序倒序** 反复从数组取值即可
![](https://img.kancloud.cn/8f/4b/8f4b02b89750914692c57f73b4e6598c_901x545.png)
![](https://img.kancloud.cn/4c/86/4c8691ca3fa7465c2a2b097ce59399b7_885x523.png)
>[danger] ##### js 解题
~~~
var sortString = function (s) {
// 将字符串根据ascii 映射放入对应数组脚标中
const array = new Array(26).fill(0)
const ascii_a = 'a'.charCodeAt(0)
for (let char of s) {
// 转换ascii 码
const idx = char.charCodeAt(0)
array[idx - ascii_a]++
}
// 按升降序依次正反数组取值
let str = ''
// 一直循环直到 新生成的字符串长度等于原来字符串长度
while (str.length < s.length) {
// 升序排列
for (let i = 0; i < 26; i++) {
if (array[i]) {
str += String.fromCharCode(i + ascii_a)
array[i]--
}
}
// 降序排列
for (let i = 25; i >= 0; i--) {
if (array[i]) {
str += String.fromCharCode(i + ascii_a)
array[i]--
}
}
}
return str
}
~~~
>[danger] ##### java 解题
~~~
public class Solution {
public String sortString(String s) {
// 创建一个26长度数组
byte[] asciiLs = new byte[26];
char asciiLs_a = 'a';
// 将字符依次保存
for(int c:s.toCharArray()){
int idx = c-asciiLs_a;
asciiLs[idx]++;
}
// 记录新的字符串 这种拼接比较慢可以使用数组List ans = new ArrayList<>();
String res = "";
while(res.length()<s.length()){
// 升序记录
for(int i=0;i<26;i++){
if(asciiLs[i]!=0){
// 找到就去掉一次
asciiLs[i]--;
res+=String.valueOf((char)(i+asciiLs_a));
}
}
// 降序
for(int i=25;i>=0;i--){
if(asciiLs[i]!=0){
// 找到就去掉一次
asciiLs[i]--;
res+=String.valueOf((char)(i+asciiLs_a));
}
}
}
return res;
}
}
~~~
>[info] ## 看到一个扩展思路
直接` while (--end >= 0)` 这种将计算放到**while** 条件中
~~~
/**
* @param {string} s
* @return {string}
*/
var sortString = function(s) {
// 计数法
// a-z => 97-122
// index是字母-97,值是出现的次数
let arr = Array(26).fill(0)
const base = 'a'.charCodeAt()
for (const char of s) {
// 0-25
arr[char.charCodeAt() - base] ++
}
let ans = ''
while (ans.length < s.length) {
let = start = -1, end = 26
while (++start < 26) {
if (arr[start] !== 0) {
ans += String.fromCharCode(start + base)
arr[start] --
}
}
while (--end >= 0) {
if (arr[end] !== 0) {
ans += String.fromCharCode(end + base)
arr[end] --
}
}
}
return ans;
};
~~~
- 刷题准备
- 统计数组中元素出现次数
- Leetcode -- 442数组中重复的数据
- leetcode -- 448 找到所有数组中消失的数字
- 字符类似题
- Leetcode -- 1002 查找共用字符
- Leetcode -- 1370上升下降字符串
- 指针类题解
- Leetcode -- 283 移动零
- Leetcode -- 26. 删除有序数组中的重复项
- Leetcode -- 80. 删除有序数组中的重复项 II
- Leetcode -- 27. 移除元素
- Leetcode -- 344. 反转字符串
- Leetcode -- 125 验证回文串
- Leetcode -- 11 盛最多水的容器
- Leetcode -- 1480. 一维数组的动态和