leetcode-有序队列

726 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

题目描述

给定一个字符串 s 和一个整数 k 。你可以从 s 的前 k 个字母中选择一个,并把它加到字符串的末尾。

返回 在应用上述步骤的任意数量的移动后,字典上最小的字符串 。

示例 1:

输入:s = "cba", k = 1
输出:"acb"
解释:
在第一步中,我们将第一个字符(“c”)移动到最后,获得字符串 “bac”。
在第二步中,我们将第一个字符(“b”)移动到最后,获得最终结果 “acb”。

示例 2:

输入:s = "baaca", k = 3
输出:"aaabc"
解释:
在第一步中,我们将第一个字符(“b”)移动到最后,获得字符串 “aacab”。
在第二步中,我们将第三个字符(“c”)移动到最后,获得最终结果 “aaabc”。

  提示:

  • 1 <= k <= S.length <= 1000
  • s 只由小写字母组成。

思路

想了好一会儿,确实没想出来。看了官方题解,感觉有些跳跃,自己记录一下理解。
分成2种情况考虑:

  • k == 1
  • k > 1

k == 1 每次只能移动对首字符到队尾,思考起来比较简单,n种情况直接比较即可。当然,看了三叶姐的题解,还可以用最小表示法,操作更少。

k > 1 这种情况重点讲一下,很多同学应该是这里不太好理解。题解给出的结论是,这种情况下总是可以构造出字典序最小的字符串,怎么证明呢?
我们先看最基础的情况,就是k=2。构造的方法如下:

  1. 将最大的字符移到对首
  2. 将最大的字符移到队尾
  3. 将第二大的字符移到对首,且最大的字符移到对首第二
  4. 讲对首2个字符打包,重复2-4步,直到全部有序 这么列出来可能还不太好理解,我们来个实走一遍,假设字符串为
b d a e c
  1. 每次移动对首1个字符到队尾,直到最大的e出现在对首
e c b d a
  1. 将已经有序的e打包,逐个移动到队尾
c b d a e
  1. 每次移动对首1个字符到队尾,直到第二大的d出现在对首
d a e c b
  1. 固定d不要动,每次移动第2个字符到队尾,直到e出现在d的后面
d e c b a
  1. 这样,de已经排好序了,打包成1个整体,逐个移动到队尾
c b a d e
  1. 此时,刚好c在对首了,如果不是c,可以逐个移动直到c到对首
c b a d e
  1. 固定对首的c不动,移动第2个字符,直到d出现在c后面,由于e紧跟d,所以此时cde有序
c d e b a
  1. cde已经排好序了,打包成1个整体,逐个移动到队尾
b a c d e
  1. 此时,刚好b在对首了,如果不是b,可以逐个移动直bc到对首
b a c d e
  1. 固定对首的b不动,移动第2个字符,直到c出现在b后面
b c d e a
  1. bcde已经排好序了,打包成1个整体,逐个移动到队尾
a b c d e

这样,排序就完成了。当k > 2时,我们可以也用这样的方式,只移动前2位到队尾,跟k = 2采取一样的策略。

Java版本代码

class Solution {
    public String orderlyQueue(String s, int k) {
        if (k == 1) {
            String ans = s;
            StringBuilder builder = new StringBuilder();
            builder.append(s);
            for (int i = 0; i < s.length() -1; i++) {
                char c = builder.charAt(0);
                builder.deleteCharAt(0);
                builder.append(c);
                if (builder.toString().compareTo(ans) < 0) {
                    ans = builder.toString();
                }
            }
            return ans;
        } else {
            char[] chars = s.toCharArray();
            Arrays.sort(chars);
            return new String(chars);
        }
    }
}