1370. 上升下降字符串
1370. 上升下降字符串
题目
You are given a string s. Reorder the string using the following algorithm:
- Remove the smallest character from
sand append it to the result. - Remove the smallest character from
sthat 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
sand append it to the result. - Remove the largest character from
sthat 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
shave 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 <= 500sconsists 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 <= 500s只包含小写英文字母。
解题思路
统计每个字符的出现次数:
- 使用一个长度为 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; // 返回结果字符串
};
