给定一个二进制字符串 s
,每秒将所有子字符串 "01"
同时替换为 "10"
,直到字符串中不再存在 "01"
。求完成这个过程所需的秒数。
输入:
s = "0101"
输出:
2
解释:
最直观的思路是模拟替换过程:
"01"
并替换为 "10"
。优点:实现简单,逻辑清晰。
缺点:时间复杂度较高,最坏情况下为 O (n²)。
观察发现:
'0'
需要向右移动的次数等于其右侧连续 '1'
的数量。'0'
右侧连续 '1'
数量的最大值。示例分析:
s = "0101"
'0'
右侧有 1 个 '1'
→ 需 1 秒。'0'
右侧有 2 个 '1'
→ 需 2 秒。优点:时间复杂度 O (n)。
缺点:需要理解并推导出数学规律。
class Solution {
public int secondsToRemoveOccurrences(String s) {
int seconds = 0;
boolean hasChanged;
char[] chars = s.toCharArray();
do {
hasChanged = false;
for (int i = 0; i < chars.length - 1; i++) {
if (chars[i] == '0' && chars[i + 1] == '1') {
// 交换 '0' 和 '1'
chars[i] = '1';
chars[i + 1] = '0';
hasChanged = true;
// 跳过下一个位置,避免重复处理
i++;
}
}
if (hasChanged) {
seconds++;
}
} while (hasChanged);
return seconds;
}
}
class Solution {
public int secondsToRemoveOccurrences(String s) {
int seconds = 0;
int ones = 0; // 当前累积的连续 '1' 数量
for (char c : s.toCharArray()) {
if (c == '0') {
// 当前 '0' 需要等待 ones 秒才能移动
seconds = Math.max(seconds, ones);
} else {
ones++;
}
}
return seconds;
}
}
初始化变量:
seconds
:记录总秒数。hasChanged
:标记本次是否发生替换。chars
:将字符串转换为字符数组以便修改。循环处理:
do-while
确保至少执行一次替换。"01"
并交换为 "10"
。i++
),避免重复处理。更新秒数:
seconds
加 1。'0'
时,记录当前累积的连续 '1'
数量 ones
,并更新最大秒数。'1'
时,累积 ones
。方法 | 时间复杂度 | 空间复杂度 |
---|---|---|
暴力模拟法 | O(n²) | O(n) |
数学规律法 | O(n) | O(1) |
最坏情况下(如 "010101..."
),每次只能处理一个 "01"
,需要进行 O (n) 次遍历,每次遍历 O (n) 时间。
'0'
必须等待其右侧的所有 '1'
全部移动到左边后,才能移动。"011"
中的 '0'
需要 2 秒才能移动到最后。字符串是不可变对象,每次修改会生成新实例。字符数组支持原地修改,减少内存开销。
输入 | 输出 | 说明 |
---|---|---|
"01" |
1 | 一次替换即可 |
"10" |
0 | 初始无 "01" |
"010101" |
3 | 每个 '0' 需要移动 3 次 |
"111000" |
0 | 初始无 "01" |
"0" |
0 | 空字符串 |
本题通过两种方法实现:
实际开发中需根据场景选择合适方法。掌握字符串处理技巧和数学规律推导能力,对解决类似问题至关重要。如果您有任何疑问或建议,欢迎在评论区交流!