计数二进制子串(力扣第696题)

题目:

给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的。

重复出现的子串要计算它们出现的次数。

示例:

输入: "00110011"
输出: 6
解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。

请注意,一些重复出现的子串要计算它们出现的次数。

另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。

输入: "10101"
输出: 4
解释: 有4个子串:“10”,“01”,“10”,“01”,它们具有相同数量的连续1和0。

分析

符合计数要求的子串,必须满足三个条件:

1、必须有0和1

2、0和1的数量相同

3、0和1必须连续结合在一起,即0和1不能交叉

方法一:

​ 暴力法,即从第一个字符开始遍历,判断从这个字符位置开始向后的子串是否有符合要求的,如果有则计数,如果没有则进行下一次遍历。在遍历的过程,从当前子串的第一个字符开始,如果其下一个字符与当前字符不相同,那么就一定是“01”或者“10”,则符合要求,直接计数,然后开始下一次遍历;如果相同,则继续遍历,记录当前连续字符的个数,然后遇到不同的字符退出当前循环,重新对新的字符进行遍历,对之前连续字符的个数进行减1运算,直到为0,则停止,并计数。

​ 暴力法,超出了时间要求,因此性能不好。

private int subStr_nums = 0;
    public int countBinarySubstrings(String s) {

        for (int i = 0; i < s.length() - 1; i++) {

            extendsSub(s,i,i+1);
        }

        return subStr_nums;
    }

    private void extendsSub(String s,int start,int end){

        if (s.charAt(start) != s.charAt(end)){
            subStr_nums ++;
            return;
        }else if (s.charAt(start) == s.charAt(end)){

            int nums1 = 0;
            while (start < s.length()-1 && s.charAt(start) == s.charAt(end)){
                nums1++;
                start++;
                end++;
            }

            while (end < s.length()-1 && s.charAt(end) == s.charAt(end+1) && nums1>0){
                nums1--;
                end++;
            }

            if (nums1 == 0){
                subStr_nums++;
            }
        }

    }

方法二:

​ 因为要寻找的符合要求的子串是0和1必须连续,不能交叉,所以这个子串可以分为两个部分,当我们在遍历整个字符串的时候,可以定义两个变量,即curLen和preLen,分别记录当前遍历的连续子串的长度,和前一次遍历的另一个连续子串的长度,只要当前连续子串的长度小于前一次连续子串的长度,那么就一定可以找到符合要求的子串。同时,curLen变为preLen的条件是,遍历字符的时候遇到了不相同的字符。

    public int countBinarySubstrings1(String s) {
        int preLen = 0, curLen = 1, count = 0;
        for (int i = 1; i < s.length(); i++) {
            if (s.charAt(i) == s.charAt(i - 1)) {
                curLen++;
            } else {
                preLen = curLen;
                curLen = 1;
            }
            if (preLen >= curLen) {
                count++;
            }
        }
        return count;
    }
原文地址:https://www.cnblogs.com/yxym2016/p/13986515.html