1. 程式人生 > 實用技巧 >上升下降字串

上升下降字串

1.問題描述

給你一個字串 s ,請你根據下面的演算法重新構造字串:

  1. s 中選出 最小 的字元,將它 接在 結果字串的後面。
  2. s 剩餘字元中選出 最小 的字元,且該字元比上一個新增的字元大,將它 接在 結果字串後面。
  3. 重複步驟 2 ,直到你沒法從 s 中選擇字元。
  4. s 中選出 最大 的字元,將它 接在 結果字串的後面。
  5. s 剩餘字元中選出 最大 的字元,且該字元比上一個新增的字元小,將它 接在 結果字串後面。
  6. 重複步驟 5 ,直到你沒法從 s 中選擇字元。
  7. 重複步驟 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 只包含小寫英文字母。

2.求解

桶排序

  • 重複若干輪以下操作

    1. 從未被選擇的字串中提取出最長的上升字串
    2. 從未被選擇的字串中提出除最長的下降字串
  • 實現1,2的方法

    因為字母的個數只有26個,建立一個大小為26的桶,先將每個字母放入桶中

    提取上升字串則順序遍歷桶

    提取下降字串則逆序遍歷桶

程式碼如下

/*
執行用時:3 ms, 在所有 Java 提交中擊敗了98.12% 的使用者
記憶體消耗:38.6 MB, 在所有 Java 提交中擊敗了70.04% 的使用者
*/
public String sortString(String s) {
    int[] nums = new int[26];
    StringBuilder res = new StringBuilder();
    for (char c : s.toCharArray()) {
        nums[c - 'a'] += 1;
    }
    while (res.length() < s.length()) {
        for (int i = 0; i < 26; i++) {
            if (nums[i] > 0) {
                res.append((char) ('a' + i));
                nums[i]--;
            }
        }
        for (int i = 25; i >= 0; i--) {
            if (nums[i] > 0) {
                res.append((char) ('a' + i));
                nums[i]--;
            }
        }
    }
    return res.toString();
}
  • 時間複雜度:O(k * n),k為字符集大小,本題為26,n是字串的長度,最壞的情況是s中的字元全部相同,這樣對於每個字元都要遍歷一遍桶
  • 空間複雜度:O(k),k為字符集大小