LeetCode 696. Count Binary Substrings

本文探讨了一种算法问题,即给定一个由0和1组成的字符串,如何计算其中包含相同数量连续0和1的子串数目。文章提供了三种解题思路及对应的代码实现,包括暴力解法、统计连续字符次数的方法以及更简洁高效的解决方案。

Give a string s, count the number of non-empty (contiguous) substrings that have the same number of 0's and 1's, and all the 0's and all the 1's in these substrings are grouped consecutively.

Substrings that occur multiple times are counted the number of times they occur.

Example 1:

Input: "00110011"
Output: 6
Explanation: There are 6 substrings that have equal number of consecutive 1's and 0's: "0011", "01", "1100", "10", "0011", and "01".

Notice that some of these substrings repeat and are counted the number of times they occur.
Also, "00110011" is not a valid substring because all the 0's (and 1's) are not grouped together.

 

Example 2:

Input: "10101"
Output: 4
Explanation: There are 4 substrings: "10", "01", "10", "01" that have equal number of consecutive 1'

题意:给定一个由0和1组成的非空字符串,计算出由相同数量的0和1、且0和1分别连续的子串的个数。
思路1:直接暴力解决,但时间复杂度高,提交后time limit exceeded。从前往后遍历,判断当前数字的连续相同数字的数量,再找出从第一个不同数字开始,连续不同数字的数量,数量相同则count加1,否则count不变。
代码如下:
public int countBinarySubstrings(String s) {
        char[] chars = s.toCharArray();
        int count = 0;
        for(int i = 0; i < chars.length - 1; i++){
            if(isSubstrings(chars, i)){
                count++;
            }
        }
        return count;
    }
    public boolean isSubstrings(char[] chars, int start){
        int same = start + 1;
        while(same < chars.length - 1 && chars[start] == chars[same]){
            same++;
        }
        int diff = same;
        while(diff < chars.length && chars[diff] != chars[start] && diff - same < same - start){
            diff++;
        }
        return diff - same == same - start ? true : false;
    }

思路2:(LeetCode提供的算法1)在字符串s中,统计相同数字连续出现了多少次。例:s = "00110",则group = {2,2,1}。这样,在统计有多少个满足条件的子串时,对group数组从前往后遍历,依次取min{group[i], group[i+1]},再求和即可。

 原因:以group[i]=2, group[i+1]=3为例,则表示“00111”或“11000”。
以“00111”为例,group={2,3},当第一个1出现时,前面已经有2个0了,所以肯定能组成01;再遇到下一个1时,此时有2个0,2个1,所以肯定能组成0011;再遇到下一个1时,前面只有2个0,而此时有3个1,所以不可以再组成满足条件的子串了。

代码如下:

public int contBinarySubstrings(String s){
        char[] chars = s.toCharArray();
        int[] group = new int[chars.length];
        int index = 0;
        group[0] = 1;
        for(int i = 1; i < chars.length; i++){
            if(chars[i] == chars[i - 1])
                group[index]++;
            else
                group[++index] = 1;
        }
        int i = 0, count = 0;
        while(i < group.length - 1 && group[i] != 0){
            count += Math.min(group[i], group[i + 1]);
            i++;
        }
        return count;
    }

思路3:(LeetCode提供的算法2)定义两个变量pre和cur,pre存储当前数字前的数字连续次数,cur存储当前数字的连续次数。然后从第二个数字开始遍历,如果当前数字与前面数字相同,则cur自增1;否则对pre和cur取最小值,记为子串次数,并将pre赋值为cur,cur重置为1。原理与上一个方法相同,但没有定义数组,空间复杂度降低。

代码如下:


public int contBinarySubstring(String s){
        int pre = 0, cur = 1, count = 0;
        for(int i = 1; i < s.length(); i++){
            if(s.charAt(i) != s.charAt(i - 1)){
                count += Math.min(pre, cur);
                pre = cur;
                cur = 1;
            }
            else{
                cur++;
            }
        }
        return count + Math.min(pre, cur);
    }

 

 

转载于:https://www.cnblogs.com/zeroingToOne/p/7852352.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值