将字符串翻转到单调递增
难度:
标签:
题目描述
代码结果
运行时间: 64 ms, 内存: 16.5 MB
/*
题目思路:
1. 我们需要找到最少的翻转次数,使得给定的二进制字符串单调递增。
2. 使用Java Stream对每一个位置计算前面的1变0和后面的0变1的最小次数。
3. 使用两个累加器leftFlip和rightFlip,分别计算前面和后面的翻转次数。
*/
import java.util.stream.IntStream;
public class Solution {
public int minFlipsMonoIncr(String s) {
int n = s.length();
int[] leftFlip = new int[n + 1];
int[] rightFlip = new int[n + 1];
IntStream.range(0, n).forEach(i -> {
leftFlip[i + 1] = leftFlip[i] + (s.charAt(i) == '0' ? 0 : 1);
});
IntStream.range(0, n).map(i -> n - 1 - i).forEach(i -> {
rightFlip[i] = rightFlip[i + 1] + (s.charAt(i) == '1' ? 0 : 1);
});
return IntStream.range(0, n + 1)
.map(i -> leftFlip[i] + rightFlip[i])
.min()
.orElse(Integer.MAX_VALUE);
}
}
解释
方法:
此题解采用一种贪心策略,通过计数器来监视已遍历的 '1' 的数量。对于每个 '0',如果在此之前有 '1' 出现(即 count > 0),则将这个 '0' 翻转为 '1' 可以使得字符串趋向单调递增,同时将计数器减一表示减少一个需要翻转的 '1',同时累加翻转次数。如果遇到 '1',则增加计数器。这种方法实际上是在模拟将一部分 '1' 向前移动到所有的 '0' 之前,每次遇到 '0' 时,如果前面有 '1',就考虑将前面的 '1' 翻转成 '0',或者将当前的 '0' 翻转成 '1',选择翻转 '0' 是因为这可以帮助维持后续的单调递增状态。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
为什么在遇到'0'时,选择翻转前面的'1'而不是直接翻转当前的'0'?
▷🦆
在这种贪心策略中,维护的'1'的计数count是否可以解释为当前需要翻转的'1'的最小数量?
▷🦆
如果输入的字符串已是单调递增,算法的输出是否为0?如果不是,应如何修改代码以处理这种特殊情况?
▷🦆
算法在遇到连续的'0'时是否会重复计算翻转次数?例如在字符串'00011000'中处理后三个'0'的逻辑是什么?
▷