1370. 上升下降字符串
1370. 上升下降字符串
题目
You are given a string s
. Reorder the string using the following algorithm:
- Remove the smallest character from
s
and append it to the result. - Remove the smallest character from
s
that is greater than the last appended character, and append it to the result. - Repeat step 2 until no more characters can be removed.
- Remove the largest character from
s
and append it to the result. - Remove the largest character from
s
that is smaller than the last appended character, and append it to the result. - Repeat step 5 until no more characters can be removed.
- Repeat steps 1 through 6 until all characters from
s
have been removed.
If the smallest or largest character appears more than once, you may choose any occurrence to append to the result.
Return the resulting string after reordering s
using this algorithm.
Example 1:
Input: s = "aaaabbbbcccc"
Output: "abccbaabccba"
Explanation: After steps 1, 2 and 3 of the first iteration, result = "abc"
After steps 4, 5 and 6 of the first iteration, result = "abccba"
First iteration is done. Now s = "aabbcc" and we go back to step 1
After steps 1, 2 and 3 of the second iteration, result = "abccbaabc"
After steps 4, 5 and 6 of the second iteration, result = "abccbaabccba"
Example 2:
Input: s = "rat"
Output: "art"
Explanation: The word "rat" becomes "art" after re-ordering it with the mentioned algorithm.
Constraints:
1 <= s.length <= 500
s
consists of only lowercase English letters.
题目大意
给你一个字符串 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"
提示:
1 <= s.length <= 500
s
只包含小写英文字母。
解题思路
统计每个字符的出现次数:
- 使用一个长度为 26 的数组
count
,表示字符'a'
到'z'
的出现次数。 - 遍历字符串
s
,通过字符的 ASCII 值计算其索引位置:count[char.charCodeAt() - 'a'.charCodeAt()]++
- 使用一个长度为 26 的数组
按照规则构建结果字符串:
- 使用一个结果字符串
res
。 - 在
res
的长度小于s
的长度时,不断执行以下两个步骤:- 从左到右(字典序递增)扫描
count
数组,将字符添加到结果字符串中并减少对应的计数。 - 从右到左(字典序递减)扫描
count
数组,将字符添加到结果字符串中并减少对应的计数。
- 从左到右(字典序递增)扫描
- 使用一个结果字符串
返回结果字符串:
- 重复上述操作,直到所有字符用完,最终返回
res
。
- 重复上述操作,直到所有字符用完,最终返回
复杂度分析
- 时间复杂度:
O(n)
,其中n
为字符串的长度。- 统计字符次数,遍历字符串
s
,复杂度为O(n)
。 - 构造结果字符串,每次遍历
count
数组需要O(26)
,总共构造字符串的长度为n
,复杂度为O(26 * n)
,即O(n)
。
- 统计字符次数,遍历字符串
- 空间复杂度:
O(n)
count
数组大小固定为 26,空间复杂度为O(1)
。- 结果字符串的空间复杂度为
O(n)
。
代码
var sortString = function (s) {
let count = new Array(26).fill(0); // 初始化字符计数数组
// 统计每个字符的出现次数
for (let char of s) {
count[char.charCodeAt() - 'a'.charCodeAt()]++;
}
let res = ''; // 结果字符串
while (res.length < s.length) {
// 当结果字符串未完成时,继续操作
for (let i = 0; i < 26; i++) {
// 从左到右(字典序递增)
if (count[i] > 0) {
res += String.fromCharCode(i + 'a'.charCodeAt());
count[i]--;
}
}
for (let i = 25; i >= 0; i--) {
// 从右到左(字典序递减)
if (count[i] > 0) {
res += String.fromCharCode(i + 'a'.charCodeAt());
count[i]--;
}
}
}
return res; // 返回结果字符串
};