【字符串】【打卡128天】:leetcode 696. 计数二进制子串

1、题目描述

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

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

2、算法分析

        本问题中对称中心只能是两个字符的中间,可以用整形序列[1, s.length() - 1]来表示回文中心的位置,那么left = i - 1, right = i 就是最中心的两个字符。
        比如i = 1时left = 0, right = 1 ,就是第一个可能的满足题目要求的子串。由原字符串中第一,第二个字符构成。
        所以遍历每一个回文中心的循环为for(int i = 1; i < s.length(); i++)
在循环中首先要保证,回文中心左右的两个字符char leftChar = chars[left], rightChar = chars[right];一个是0,另外一个是1。
        如果都是1或者都是0,那么没有以这个为中心的符合要求的字串,后续就不用从中心向外扩展了if(leftChar == rightChar) continue;。
        如果leftChar != rightChar,就以此为中心,。使用一个while循环来计数这个中心有多少个符合题意的子串。循环条件首先保证索引不越界,其次leftChar左边的字符都要和它相等,rightChar右边的字符都要和它相等。不断向外扩展就是left--; right++;

注意以下几点:

①子串中具有相同数量的0和1,且出现的次数都是相同的。000111 01  1100

②00110011不是有效的子串,因为所有的1和0没有组合在一起。

③转换成字符数组的时候,注意数组的长度是1,长度范围需要是字符串的长度、

经过分析题目中的意思,接下来就好办了。可以使用中心扩展法。之前做过一题,求回文子串。

3、代码实现

public int countBinarySubstrings(String s) {
        int result = 0;
        char[] chars = s.toCharArray();
        // 遍历分析
        for(int i = 1; i < s.length(); i++){
            int left = i - 1, right = i;
            char leftChar = chars[left], rightChar = chars[right];
            //如果相邻且相等,那么不符合题目要求继续往下找。
            if(leftChar == rightChar)
                continue;
            // 中心向左向右扩展
            while(left >= 0 && right < s.length() && chars[left] == leftChar && chars[right] == rightChar){
                left--;
                right++;
                result++;
            }
        }
        return result;
    }

Guess you like

Origin blog.csdn.net/Sunshineoe/article/details/121662012