[LeetCode]899. 有序队列

75 篇文章 0 订阅

题目

899. 有序队列


899. 有序队列
给定一个字符串 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 只由小写字母组成。

解法

方法1:最小表示法

  • 当k=1时,即求字符串的最小表示法

  • 当k>1时,每次可以调整开头的的至少两个字符的位置,如bazzz-> bzzza -> zzzab …->abzzz,对于在排序算法中,值需要交换相邻的两个字符可以实现序列有序,所以这种情况下只需要字符串排序即可

  • 当 K = 2 时,可以发现,我们能够交换字符串中任意两个相邻的字母。具体地,设字符串 S 为 S[1], S[2], …, S[i], S[i + 1], …, S[N],我们需要交换 S[i] 和 S[j]。首先我们依次将 S[i] 之前的所有字符依次移到末尾,得到

    S[i], S[i + 1], …, S[N], S[1], S[2], …, S[i - 1]

    随后我们先将 S[i + 1] 移到末尾,再将 S[i] 移到末尾,得到

    S[i + 2], …, S[N], S[1], S[2], …, S[i - 1], S[i + 1], S[i]

    最后将 S[i + 1] 之后的所有字符依次移到末尾,得到

    S[1], S[2], …, S[i - 1], S[i + 1], S[i], S[i + 2], …, S[N]

    这样就交换了 S[i] 和 S[i + 1],而没有改变其余字符的位置。

    当我们可以交换任意两个相邻的字母后,就可以使用冒泡排序的方法,仅通过交换相邻两个字母,使得字符串变得有序。因此当 K = 2 时,我们可以将字符串移动得到最小的字典序。

    当 K > 2 时,我们可以完成 K = 2 时的所有操作。

        public String orderlyQueue(String s, int k) {
            if (k == 1) return getMin(s);
            char[] ch = s.toCharArray();
            Arrays.sort(ch);
            return String.valueOf(ch);
        }

        public String getMin(String s) {
            int n = s.length();
            s = s + s;
            int i = 0, j = 1;
            while (i < n && j < n) {
                int p = 0;
                while (p < n && s.charAt(i + p) == s.charAt(j + p)) p++;
                if (s.charAt(i + p) > s.charAt(j + p)) {
                    i += p + 1;
                } else {
                    j += p + 1;
                }
                if (i == j) j++;
            }
            int q = Math.min(i, j);
            return s.substring(q, q + n);
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值