题目:有序队列
题意:给定一个字符串 s 和一个整数 k 。你可以从 s 的前 k 个字母中选择一个,并把它加到字符串的末尾。
返回 在应用上述步骤的任意数量的移动后,字典上最小的字符串 。
示例 1:
输入:s = "cba", k = 1
输出:"acb"
解释:
在第一步中,我们将第一个字符(“c”)移动到最后,获得字符串 “bac”。
在第二步中,我们将第一个字符(“b”)移动到最后,获得最终结果 “acb”。
示例 2:
输入:s = "baaca", k = 3
输出:"aaabc"
解释:
在第一步中,我们将第一个字符(“b”)移动到最后,获得字符串 “aacab”。
在第二步中,我们将第三个字符(“c”)移动到最后,获得最终结果 “aaabc”。
题解:
当 K = 1 时, 只能循环移动每个元素,无法改变相对位置。因此只需要获取循环移动过程中字典序最小的序列。
当 K > 1 时, 可以生成当前字符串的任意序列,(有点像冒泡排序)。因此将原字符串排序生成字典序最小的序列。
解释:
如:s = "bdeca", k = 2;
1、 经过若干次移动,s的第一位可以变为'e',此时保持第一位不一定,第二位一直移动到最后,直到第二位为字符'd',
如此前两个字符可以按照字符排序了;(当然第一位为'd',第二位为'e',也没问题,反正是从前k位中任意选一位到末尾)
在前两位中将'd'移动到字符串末尾,随后将'e'移动到字符串末尾;这时有了排序 "de";
字符串s前两位又空出来可以来移动字符了;
2、 经过一段时间移动,有可以将字符'c'移动到第一位,随后利用第二位来移动其它字符,直到字符'd'到达第二位,
这时候字符'd'之后的位置是字符'e';
将字符'c'移动到末尾,随后将字符'd'移动到末尾,最后将字符'e'移动到末尾;
这样又形成排序"cde"
3、如此反复,一定能形成升序的字符串"abcde";
具体步骤演示:
原始: s = "bdeca", k = 2;
第一次: s = "decab"; //注意此时d在第一位了,那么就不要移动d了,又刚好e在前两位中;那么将d,e分别移动到末尾即可;
第二次: s = "ecabd";
第三次: s = "cabde"; //看到了吗,最后两位已经是升序了"de"; 接下来将c移动到第一位,然后想办法将de移动到第二,第三位;
//这里c刚好是第一位;
第四次: s = "cbdea";
第五次: s = "cdeab"; //就是这样,然后分别将c,d,e移动到最后;
第六次: s = "deabc";
第七次: s = "eabcd";
第八次: s = "abcde"; //看,最后三位又是升序了,"cde";
//接下来依次类推
第九次: s = "bcdea"; //b跟有序子串首字母c在前两位了,那就准备生成更大的有序子串吧!
第十次: s = "cdeab";
第十一次: s = "deabc";
第十二次: s = "eabcd";
第十三次: s = "abcde"; //最终结果;
当然 k=2 都能成功将无序字符串变为有序,k>2的就更没问题了;
所以我们需要判断的只有 k=1 以及 k>1 的情况即可;
附上leetcode官方代码:
class Solution {
public:
string orderlyQueue(string s, int k) {
if (k == 1) {
string smallest = s;
int n = s.size();
for (int i = 1; i < n; i++) {
char c = s[0];
//这一步是将s变为其自身的子串,从下标从1开始,直到末尾
s = s.substr(1);
s.push_back(c);
if (s < smallest) {
smallest = s;
}
}
return smallest;
} else {
sort(s.begin(), s.end());
return s;
}
}
};