20分钟题解--上升下降字符串

218 阅读1分钟

题目描述

给你一个字符串 s ,请你根据下面的算法重新构造字符串:

1、从 s 中选出 最小 的字符,将它 接在 结果字符串的后面。 2、从 s 剩余字符中选出 最小 的字符,且该字符比上一个添加的字符大,将它 接在 结果字符串后面。 3、重复步骤 2 ,直到你没法从 s 中选择字符。 4、从 s 中选出 最大 的字符,将它 接在 结果字符串的后面。 5、从 s 剩余字符中选出 最大 的字符,且该字符比上一个添加的字符小,将它 接在 结果字符串后面。 6、重复步骤 5 ,直到你没法从 s 中选择字符。 7、重复步骤 1 到 6 ,直到 s 中所有字符都已经被选过。 在任何一步中,如果最小或者最大字符不止一个 ,你可以选择其中任意一个,并将其添加到结果字符串。

请你返回将 s 中字符重新排序后的 结果字符串 。

  • 提示
  • 1 <= s.length <= 500
  • s 只包含小写英文字母。

示例

示例 1:

输入:s = "aaaabbbbcccc"
输出:"abccbaabccba"
解释:第一轮的步骤 123 后,结果字符串为 result = "abc"
第一轮的步骤 456 后,结果字符串为 result = "abccba"
第一轮结束,现在 s = "aabbcc" ,我们再次回到步骤 1
第二轮的步骤 123 后,结果字符串为 result = "abccbaabc"
第二轮的步骤 456 后,结果字符串为 result = "abccbaabccba"

示例 2:

输入:s = "leetcode"
输出:"cdelotee"

题解

这个题,仔细分析后,其实就两步操作,首先按升序排列所有字符,然后再按降序排列所有字符。每次排列都要耗费字母个数。前提条件是原始字符串只有26种英文字母,且可能出现重复。

第一步,分析思路

这样分析后,第一步要做的就是整理出解法思路:可以这么想:把原字符串打散,一个个放入一个容器中,容器大小是26个空位,按a-z的顺序来,遇到重复的字符就占同一个位子。

第二步,数据结构

如何实现呢?可以像这样定义一个26个长度的数组,我们知道'a'的Unicode编码,'a'.charCodeAt()等于97,且这个97是26个英文字母中最小的,那遍历字符串后,每个字符的减97就巧妙地代表了索引,i从0到25代表a-z;最后就是遍历时,在遇到每个字符时,数组num[i]++,这样就能表示原字符串中对应字符出现的次数了。 这部分代码就是这样:

var s = 'aaabbbcccaa'
const num = new Array(26).fill(0);
for (let ch of s) {
        num[ch.charCodeAt() - 'a'.charCodeAt()]++;
    }
//num = [5,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

第三步,遍历

看上面代码,有了这样的数组num,我们就可以进行题目中的操作了,一次升序,一次降序;升序就是从上面的数组num中从0到25去找,降序就是从25到0去找;每找到一次,num[i]--一次,直到num[i]的值为0;

到这里,思路就很明显了,代码表达就是这样:

let ret = '';
    while (ret.length < s.length) {
        for (let i = 0; i < 26; i++) {
            if (num[i]) {
                ret += String.fromCharCode(i + 'a'.charCodeAt());
                num[i]--;
            }
        }
        for (let i = 25; i >= 0; i--) {
            if (num[i]) {
                ret += String.fromCharCode(i + 'a'.charCodeAt());
                num[i]--;
            }
        }
    }
    return ret;

这道题主要是借助了charCodeAt和fromCharCode这两个api,构造了num这个关键数组。 来看下完整代码:

var sortString = function(s) {
    const num = new Array(26).fill(0);
    for (let ch of s) {
        num[ch.charCodeAt() - 'a'.charCodeAt()]++;
    }

    let ret = '';
    while (ret.length < s.length) {
        for (let i = 0; i < 26; i++) {
            if (num[i]) {
                ret += String.fromCharCode(i + 'a'.charCodeAt());
                num[i]--;
            }
        }
        for (let i = 25; i >= 0; i--) {
            if (num[i]) {
                ret += String.fromCharCode(i + 'a'.charCodeAt());
                num[i]--;
            }
        }
    }
    return ret;
};

来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/in…