题目:字典序最小的01字符串
问题描述
小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'
问题理解
给定一个由0和1组成的字符串 s,长度为 n,最多可以进行 k 次相邻字符交换操作。目标是使得字符串的字典序最小。
数据结构选择
- 字符数组:用于存储字符串的字符,以便于进行交换操作。
算法步骤
-
初始化:
- 将字符串转换为字符数组,以便于进行交换操作。
-
遍历字符数组:
-
从左到右遍历字符数组,对于每个字符
s[i]:- 如果当前字符是'1',尝试将'0'移到前面,直到达到
k次操作的限制。 - 每次交换后,更新
k的值。
- 如果当前字符是'1',尝试将'0'移到前面,直到达到
-
-
交换操作:
- 从当前位置开始,尝试将'0'移到前面,直到达到
k次操作的限制。 - 每次交换后,更新
k的值。
- 从当前位置开始,尝试将'0'移到前面,直到达到
-
返回结果:
- 将字符数组转换回字符串并返回。
代码实现
public class Main {
public static String solution(int n, int k, String s) {
char[] chars = s.toCharArray();
for (int i = 0; i < n && k > 0; i++) {
if (chars[i] == '0') {
// 计算0能往左移动的最大步数
int j = i;
while (j > 0 && chars[j - 1] == '1' && k > 0) {
// 交换
chars[j] = chars[j - 1];
chars[j - 1] = '0';
j--;
k--; // 每次交换消耗一次操作
}
}
}
return new String(chars);
}
public static void main(String[] args) {
System.out.println(solution(5, 2, "01010").equals("00101")); // true
System.out.println(solution(7, 3, "1101001").equals("0110101")); // true
System.out.println(solution(4, 1, "1001").equals("0101")); // true
}
}
关键点
- 字符数组转换:将字符串转换为字符数组以便于交换操作。
- 遍历字符数组:遍历字符数组,找到第一个'1'的位置。
- 交换操作:从该位置开始,尝试将'0'移到前面,直到达到
k次操作的限制。 - 更新
k:每次交换后,更新k的值。
复杂度分析
- 时间复杂度:O(n^2),在最坏情况下,每个字符都需要进行
k次交换。 - 空间复杂度:O(n),用于存储字符数组。
做题心得
- 这个问题通过贪心算法来解决,每一步都选择当前最优的操作,以期望最终得到字典序最小的字符串。