算法练习5:二进制字符串前缀一致的次数

给你一个长度为 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]数组的总和如果等于\frac{(min+max)*max}{2}就可以说明是连续的,其中min和max分别为当前[1, i]中的最小值和最大值。

缺陷就是,\frac{(min+max)*max}{2}求出的值会超出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;
    }
}

你可能感兴趣的:(算法,算法,leetcode,Java)