题目描述
小U拥有一个由0和1组成的字符串,她可以进行最多k次操作,每次操作可以交换相邻的两个字符。目标是通过这些操作,使得最终得到的字符串字典序最小。
例如,小U当前有一个字符串 01010,她最多可以进行 2 次相邻字符交换操作。通过这些操作,她可以将字符串调整为 00101,这是可以通过不超过2次操作得到的字典序最小的字符串。
现在,小U想知道,经过最多k次操作后,能够得到的字典序最小的字符串是什么。
测试样例
样例1:
输入:
n = 5, k = 2, s = "01010"
输出:'00101'
样例2:
输入:
n = 7, k = 3, s = "1101001"
输出:'0110101'
样例3:
输入:
n = 4, k = 1, s = "1001"
输出:'0101'
思路
解题思路
-
理解问题:首先需要通过交换相邻字符来最小化字符串的字典序。每次交换可以改变字符串的顺序,但需要在
k次操作内完成。 -
选择数据结构:可以使用一个数组来表示字符串,这样可以方便地进行交换操作。
-
算法步骤:
- 遍历字符串,找到当前最小的字符。
- 计算将这个最小字符移动到当前位置所需的最小交换次数。
- 如果交换次数不超过
k,则进行交换,并更新k。 - 继续遍历字符串的剩余部分,重复上述步骤。
c++代码
#include <iostream>
#include <vector>
#include <string>
using namespace std;
string solution(int n, int k, string s) {
// 将字符串转换为字符数组,方便进行交换操作
vector<char> chars(s.begin(), s.end());
// 遍历字符串
for (int i = 0; i < n; ++i) {
// 找到从当前位置 i 开始的最小字符
int minIndex = i;
for (int j = i + 1; j < n; ++j) {
if (chars[j] < chars[minIndex]) {
minIndex = j;
}
}
// 计算将最小字符移动到当前位置 i 所需的交换次数
int swapsNeeded = minIndex - i;
// 如果交换次数不超过 k,则进行交换
if (swapsNeeded <= k) {
// 将最小字符移动到当前位置 i
while (minIndex > i) {
swap(chars[minIndex], chars[minIndex - 1]);
minIndex--;
}
// 更新剩余的交换次数
k -= swapsNeeded;
}
}
// 将字符数组转换回字符串并返回
return string(chars.begin(), chars.end());
}
int main() {
cout << (solution(5, 2, "01010") == "00101") << endl;
cout << (solution(7, 3, "1101001") == "0110101") << endl;
cout << (solution(4, 1, "1001") == "0101") << endl;
return 0;
}
关键步骤
- 找到最小字符:在当前位置
i之后的子字符串中找到最小的字符。 - 计算交换次数:计算将这个最小字符移动到当前位置
i所需的交换次数。 - 执行交换:如果交换次数不超过
k,则进行交换,并更新k。
时间复杂度分析
-
外层循环:
- 外层循环遍历字符串的每个字符,循环次数为
n。
- 外层循环遍历字符串的每个字符,循环次数为
-
内层循环:
- 在每次外层循环中,内层循环从当前位置
i开始,找到从i到n-1的最小字符。这个内层循环的次数为n - i。
- 在每次外层循环中,内层循环从当前位置
-
交换操作:
- 如果找到的最小字符需要交换到当前位置
i,则进行交换操作。交换操作的次数为minIndex - i,在最坏情况下,这个值可以达到n - i。
- 如果找到的最小字符需要交换到当前位置
总时间复杂度
- 内层循环:每次内层循环的次数为
n - i,总的时间复杂度为O(n^2)。 - 交换操作:在最坏情况下,每次交换操作的次数为
n - i,总的时间复杂度为O(n^2)。
因此,总的时间复杂度为 O(n^2)。
总结
当前代码的时间复杂度为 O(n^2),这是因为在最坏情况下,每次外层循环都需要遍历剩余的字符串来找到最小字符,并且可能需要进行多次交换操作。这是目前的一个思路, 可能后续会有更好的想法