算法修炼之路—【字符串】Leetcode 696 计数二进制子串

文章目录

  • 题目描述
    • 思路分析
    • 解题代码
    • 复杂度分析
    • Github源码

题目描述

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

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

示例1:

输入: s = “00110011”
输出: 6
解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011”和“01”
注意: 一些重复出现的子串要计算它们出现的次数。另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。

示例2:

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

注意:

  • s.length150,000之间;
  • s只包含“0”或“1”字符

思路分析

题目难度为简单 ,这道题目让我想起了电路中的跳变沿,所以也采用跳变沿检测 + 两边延伸计数 的方法来解题:

  1. 首先需要检测出0 -> 11 -> 0的字符所处位置;
  2. 其次,采用“双指针法”来检测两边相同字符的长度,这个长度就是此跳变沿所涵盖的具有相同数量01的非空(连续)子字符串的数量。

这里我们需要设置两个指针,即leftIndex, rightIndex,对于步骤1 跳变沿检测,我们以while(rightIndex + 1 < s.length())为循环条件,判断s.charAt(rightIndex) != s.charAt(rightIndex + 1)来判断是否为跳变沿;对于步骤2,我们在检测到跳变沿后,令leftIndex == rightIndex++,此时两指针分别位于跳变两端,分别向各自方向遍历,检测符合题意的子串数量。

解题代码

    public static int solution(String s) {
    
    	int res = 0;
        int leftIndex = 0, rightIndex = 0;
        
        while(rightIndex+1 < s.length()){
            if(s.charAt(rightIndex) == s.charAt(rightIndex + 1))
                rightIndex++;
            else{
                res++;
                leftIndex = rightIndex++;
                
                while((leftIndex - 1)>=0 && (rightIndex+1)<s.length()
                        && (s.charAt(leftIndex)==s.charAt(--leftIndex)
                            && s.charAt(rightIndex)==s.charAt(++rightIndex)) )
                    res++;
            }
        }
        return res;
    }

复杂度分析

我们设ns的字符串长度

时间复杂度: 我们会字符串进行大于等于一次,最多两次的字符串访问,故时间复杂度为O(n);
空间复杂度: 没有借助辅助容器,故空间复杂度为O(1);

Github源码

完整可运行文件请访问GitHub。

你可能感兴趣的:(算法修炼之路)