LeetCode-Count Binary Substrings

本文探讨了一种算法问题,即在给定的二进制字符串中,如何有效地计算那些由连续0和1组成的子串数量。文章提出了三种解决方案,包括遍历查找、存储连续字符长度以及优化的连续长度比较方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description:
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's and 0's.

Note:

  • s.length will be between 1 and 50,000.
  • s will only consist of “0” or “1” characters.

题意:给定一个只包含0和1的字符串,找出所有有连续1和连续0组成的字串,返回结果数;

解法一(超时):对字符串进行遍历,找出每一次的连续0或者1后,看是否可以再后面连续相同长度的字符串中找到匹配的连续0或者1;

Java
class Solution {
    public int countBinarySubstrings(String s) {
        int cnt = 0;
        for (int i = 0; i < s.length() - 1; i++) {
            int index = i;
            String temp = null;
            while (index < s.length() && s.charAt(i) == s.charAt(index)) index++;
            temp = s.substring(Math.min(index, s.length() - 1), 
                               Math.min(index + index - i, s.length()));
            cnt = temp.length() == (index - i) && isSame(temp) ? cnt + 1 : cnt;
        }
        return cnt;
    }
    
    private boolean isSame(String s) {
        for (int i = 0; i < s.length() - 1; i++) {
            if (s.charAt(i) != s.charAt(i + 1)) {
                return false;
            }
        }
        return true;
    }
}

解法二:每一次都要从当前位置重新遍历寻找连续的0或者1花费的时间代价太高了;考虑字符串“000111”一共有“000111”、“0011”、“01”三种组合方式,那么我们就可以将每个连续的0或者1的长度存储起来,连续的0和1之间最短的那个长度就是所有的组合方式;

Java
class Solution {
    public int countBinarySubstrings(String s) {
        int result = 0;
        List<Integer> group = new ArrayList<>();
        int len = 1;
        for (int i = 0; i < s.length() - 1; i++) {
            if (s.charAt(i) == s.charAt(i + 1)) {
                len++;
            } else {
                group.add(len);
                len = 1;
            }
        }
        group.add(len);
        for (int i = 0; i < group.size() - 1; i++) {
            result += Math.min(group.get(i), group.get(i + 1));
        }
        return result;
    }
}

解法三:针对第二种要保存每一个连续的0或1的长度来说,我们可以只保存前一个和当前的连续0或者1的长度,这样得到的组合数是Math.min(前一个连续0或者1的长度, 当前连续0或者1的长度);

Java
class Solution {
    public int countBinarySubstrings(String s) {
        int pre = 0;
        int cur = 1;
        int result = 0;
        for (int i = 0; i < s.length() - 1; i++) {
            if (s.charAt(i) == s.charAt(i + 1)) {
                cur++;
            } else {
                result += Math.min(pre, cur);
                pre = cur;
                cur = 1;
            }
        }
        result += Math.min(pre, cur);
        return result;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值