LWC 54:696. Count Binary Substrings

LWC 54:696. Count Binary Substrings

传送门:696. Count Binary Substrings

Problem:

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.

思路1:
实际上,对于每一位都只可能出现1次合法答案或者0次答案。因为如果存在第二个合法答案,一定不符合group的条件,比如“0011”和“1100”是无法合并在一块构成新的合法答案。

代码如下:

    public int countBinarySubstrings(String s) {

        int n = s.length();
        char[] cs = s.toCharArray();

        int cnt = 0;
        for (int i = 1; i < n; ++i){
            if (group(cs, i)) cnt ++;
        }
        return cnt;
   }

    boolean group(char[] cs, int j){
        int cnt = 1;
        int pre = cs[j] - '0';
        j --;

        while (j >= 0 && cs[j] - '0' == pre) {
            cnt ++;
            j --;
        }

        while (j >= 0 && cs[j] - '0' != pre && cnt != 0) {
            cnt --;
            j --;
        }

        return cnt == 0;
    }

思路2:
单纯的来看”00111”,它的个数为min(0出现的次数,1出现的次数),所以代码如下:(注意交替更新)

    public int countBinarySubstrings(String s) {
        int n = s.length();
        char[] cs = s.toCharArray();

        int now = cs[0] - '0';
        int cnt = 0;
        int ans = 0;
        int lst = 0;

        for (int i = 0; i < n; ++i) {
            if (now != cs[i]) {
                ans += Math.min(cnt, lst);
                lst = cnt;
                cnt = 1;
                now = cs[i];
            }
            else {
                cnt ++;
            }
        }

        ans += Math.min(cnt, lst);
        return ans;
    }

思路3:
采用map,累加和,把0011映射成数组{-1,-1,1,1},再求累加和得到{0,-1,-2,-1,0},所以出现-1的两个位置组成的subSeqence一定是可能的候选值,再判断是否符合group。

代码如下:

    public int countBinarySubstrings(String s) {
        int n = s.length();
        char[] cs = s.toCharArray();
        int[] num = new int[n];
        for (int i = 0; i < n; ++i) {
            num[i] = cs[i] == '0' ? - 1 : 1;
        }

        int[] sum = new int[n + 1];
        for (int i = 0; i < n; ++i) {
            sum[i + 1] = sum[i] + num[i];
        }

        Map<Integer, Integer> map = new HashMap<>();
        map.put(0, 0);
        int cnt = 0;
        for (int i = 1; i <= n; ++i) {
            if (map.containsKey(sum[i])) {
                if (group(cs, map.get(sum[i]), i - 1)) cnt++;

            }
            map.put(sum[i], i);
        }
        return cnt;
    }

    boolean group(char[] cs, int i, int j) {
        int prev = cs[i] - '0';
        int n = j - i + 1;
        for (int k = 1; k < n / 2; ++k) {
            if (prev != cs[k + i] - '0') return false; 
        }
        return true;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值