给你一个长度为 n 、下标从 1 开始的二进制字符串,所有位最开始都是 0 。我们会按步翻转该二进制字符串的所有位(即,将 0 变为 1)。
给你一个下标从 1 开始的整数数组 flips ,其中 flips[i] 表示对应下标 i 的位将会在第 i 步翻转。
二进制字符串 前缀一致 需满足:在第 i 步之后,在 闭 区间 [1, i] 内的所有位都是 1 ,而其他位都是 0 。
返回二进制字符串在翻转过程中 前缀一致 的次数。
来源:力扣(LeetCode)
注意:此题下标是从1开始的
思路1:当出现前缀一致时,此时的[1, i]数组中一定存在1且一定是连续的,比如说[2, 3, 1, 5, 4]中[1, 4]数组存在1但不连续所以不存在前缀一致,而[1, 5]数组存在1且连续则存在前缀一致。
而要判断数组是否连续,我使用的是求和的方法(存在缺陷,但可以解决),也就是当前[1, i]数组的总和如果等于就可以说明是连续的,其中min和max分别为当前[1, i]中的最小值和最大值。
缺陷就是,求出的值会超出int范围,该题的最大范围可以使用long实现。
代码1:
class Solution {
public int numTimesAllBlue(int[] flips) {
int n = flips.length;
int ans = 0;
int cur_sum = 0;
Long min = Long.MAX_VALUE, max = Long.MIN_VALUE;
boolean check = false;
for(int i = 0; i < n; i++){
cur_sum += flips[i];
dp[flips[i]] = 1;
min = flips[i] < min ? flips[i] : min;
max = flips[i] > max ? flips[i] : max;
Long cur_sum_len = ((min+max)*max)/2;
if(flips[i] == 1){
check = true;
}
if(check && cur_sum == cur_sum_len){
ans++;
}
// System.out.println(min + " "+ max + " " + cur_sum + " " + ((min+max)*max)/2);
}
return ans;
}
}
思路2:[1, i]若是连续的,则当前数组中的最大值等于当前下标i,也就是说在[2, 3, 1, 5, 4]中,当i = 3时,此时[1, 3]的最大值等于i,且当i = 5时,[1, 5]的最大值等于i,所以有两个前缀一致。
class Solution {
public int numTimesAllBlue(int[] flips) {
int n = flips.length;
int ans = 0, max = Integer.MIN_VALUE;
for(int i = 0; i < n; i++){
max = flips[i] > max ? flips[i]:max;
if(max == (i+1)){
ans++;
}
}
return ans;
}
}