从零开始刷Leetcode day11 计数二进制子串(Count Binary Substrings)

计数二进制子串-java解法

给定一个字符串 s,计算具有相同数量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.

示例 1 :

输入: “00110011”
输出: 6
解释::有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。

请注意,一些重复出现的子串要计算它们出现的次数。

另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。
示例 2 :

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

注意:

s.length 在1到50,000之间。
s 只包含“0”或“1”字符。

解法:

我们可以将字符串 ss 按照 00 和 11 的连续段分组,存在 \rm countscounts 数组中,例如 s = 00111011s=00111011,可以得到这样的 \rm countscounts 数组:{\rm counts} = {2, 3, 1, 2}counts={2,3,1,2}。

这里 \rm countscounts 数组中两个相邻的数一定代表的是两种不同的字符。假设 \rm countscounts 数组中两个相邻的数字为 uu 或者 vv,它们对应着 uu 个 00 和 vv 个 11,或者 uu 个 11 和 vv 个 00。它们能组成的满足条件的子串数目为 \min { u, v }min{u,v},即一对相邻的数字对答案的贡献。

我们只要遍历所有相邻的数对,求它们的贡献总和,即可得到答案

代码:

class Solution {
    public int countBinarySubstrings(String s) {
        List<Integer> res = new ArrayList<>();
        int ptr = 0;
        
        int n = s.length();
        while(ptr<n){
            int count = 0;
            char cur = s.charAt(ptr);
            while(ptr < n &&  cur == s.charAt(ptr)){
                ptr++;
                count++;
            }res.add(count);
        }int ans = 0;
        for(int i =1;i<res.size();i++){
            ans += Math.min(res.get(i),res.get(i-1));
        }return ans;
    }
}

优化
上面的解法中,空间复杂度为O(n),实际上对于某一个位置 ii,其实我们只关心 i - 1i−1 位置的 \rm countscounts 值是多少,所以可以用一个 \rm lastlast 变量来维护当前位置的前一个位置,这样可以省去一个 \rm countscounts 数组的空间。
代码:

class Solution {
    public int countBinarySubstrings(String s) {
        int ptr = 0;
        int res = 0;
        int last = 0;
        int n = s.length();
        while(ptr<n){
            int count = 0;
            char cur = s.charAt(ptr);
            while(ptr < n &&  cur == s.charAt(ptr)){
                ptr++;
                count++;
            }res += Math.min(last,count);
            last = count;
            }return res;
    }
}

你可能感兴趣的:(从零开始刷Leetcode)