• 计数二进制子串(力扣第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;
        }
    
  • 相关阅读:
    cf581B Luxurious Houses
    cf581A Vasya the Hipster
    2015.9.11模拟赛 codevs4162 bzoj1774【无双大王】
    2015.9.11模拟赛 codevs 4160【会玩的】
    2015.9.11模拟赛 codevs 4159【hzwer的迷の数列】
    bzoj2019 [Usaco2009 Nov]找工作
    贪吃蛇!!!
    bzoj3850 ZCC Loves Codefires
    cf509E Pretty Song
    cf509C Sums of Digits
  • 原文地址:https://www.cnblogs.com/yxym2016/p/13986515.html
Copyright © 2020-2023  润新知