Skip to main content

0899 - Orderly Queue (Hard)

https://leetcode.com/problems/orderly-queue/

Problem Statement

You are given a string s and an integer k. You can choose one of the first k letters of s and append it at the end of the string..

Return the lexicographically smallest string you could have after applying the mentioned step any number of moves.

Example 1:

Input: s = "cba", k = 1
Output: "acb"
Explanation:
In the first move, we move the 1st character 'c' to the end, obtaining the string "bac".
In the second move, we move the 1st character 'b' to the end, obtaining the final result "acb".

Example 2:

Input: s = "baaca", k = 3
Output: "aaabc"
Explanation:
In the first move, we move the 1st character 'b' to the end, obtaining the string "aacab".
In the second move, we move the 3rd character 'c' to the end, obtaining the final result "aaabc".

Constraints:

  • 1 <= k <= s.length <= 1000
  • s consist of lowercase English letters.

Approach 1: Rotate or Sort

Written by @wingkwong
// Time Complexity: O(N ^ 2)
// Space Complexity: O(N)
class Solution {
public:
// just a refresher ...
void bubbleSort(string& s) {
int n = s.size();
bool swapped;
for (int i = 0; i < n; i++) {
swapped = false;
for (int j = 0; j < n - 1; j++) {
if (s[j] > s[j + 1]) {
swap(s[j], s[j + 1]);
swapped = true;
}
}
if (!swapped) break;
}
}

string orderlyQueue(string s, int k) {
string ans = s;
if (k == 1) {
// "cba" -> "bac" -> "acb" -> "cba" -> ...
// we only have N swaps here
// as it will become the original string after N swaps
// hence, we can try all N possible swaps and find the lexicographically smallest one
for (int i = 1; i < s.size(); i++) {
ans = min(ans, s.substr(i) + s.substr(0, i));
}
} else {
// if k > 1, we can move any character to any position by swapping two adjacent characters
// By swapping a number of times,
// e.g. "cab"
// eventually we could have "abc", "acb", "bca", "bac", "cba", "cab" (3 * 2 * 1 = 6 possible arrangements)
// so the lexicographically smallest string would be the sorted string using bubble sort
bubbleSort(ans);
// alternatively, you can use `sort(ans.begin(), ans.end());`
}
return ans;
}
};

Approach 2: Booth's Algorithm

Written by @wingkwong
class Solution {
public:
string orderlyQueue(string s, int k) {
if (k > 1) {
sort(s.begin(), s.end());
return s;
}
// case: k == 1
// Booth's algorithm uses a modified preprocessing function from KMP
// and it runs in O(N) time
// ref: https://en.wikipedia.org/wiki/Lexicographically_minimal_string_rotation
int n = s.size();
s += s;
vector<int> f(s.size(), -1);
k = 0;
for (int j = 1; j < s.size(); j++) {
char sj = s[j];
int i = f[j - k - 1];
while (i != -1 && sj != s[k + i + 1]) {
if (sj < s[k + i + 1]) k = j - i - 1;
i = f[i];
}
if (sj != s[k + i + 1]) {
if (sj < s[k]) {
k = j;
}
f[j - k] = -1;
} else {
f[j - k] = i + 1;
}
}
return s.substr(k, s.size() / 2);
}
};