002.leetcode696.计算二进制子串-Javascript

375 阅读2分钟

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

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

示例 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”字符。

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/co… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

方法1:

/**
 * @param {string} s
 * @return {number}
 */
var countBinarySubstrings = function(s) {
    let n = 0
    let my_match = str => {
        let arr1 = str.match(/^(0+|1+)/)[0]
        let arr2 = (arr1[0] ^ 1).toString().repeat(arr1.length)
        //let re_ex = new RegExp(`^${arr1}${arr2}`)
        //if(re_ex.test(str)){
        let str2 = arr1 + arr2
        if(str.startsWith(str2)){
            n++
        }
    }
    for(let i = 0; i < s.length - 1; i++){
        my_match(s.slice(i))
    }
    return n
};

思路:

![image-20200715091554699](/Users/xhx/Library/Application Support/typora-user-images/image-20200715091554699.png)

先找规律,发现适合迭代或者递归,取前几位相同的数字,然后再取反,组合成一个字符串,再去原字符串中匹配

方法2:

let countBinarySubstrings = function (s) {
  let n = 0, arr = s.match(/([1]+)|([0]+)/g)
  for (let i = 0; i < arr.length - 1; i++) {
    n += Math.min(arr[i].length, arr[i + 1].length)
  }
  return n
}

思路:

  • 000111必定有三个子串
  • 00011必定有两个子串
  • 0111必定有1个子串 以此类推, 每两组数据之间长度最短的值为子串的数量

方法3:

//伪代码
for(let i = 0; i < Math.floor(s.length/2); i++){
  s1 += '1'
  s2 += '0'
  s3 = s1 + s2
  s4 = s2 + s1
  result = result + s.match(s3).length + s.match(s4).length
}

思路:

暴力尝试,将所有可能的10 组合都试一遍

试错1:

export default s => {
  let n = 0
    let my_match = str => {
        let arr1 = str.match(/^(0+|1+)/)[0]
        let arr2 = (arr1[0] ^ 1).toString().repeat(arr1.length)
        let re_ex = new RegExp(`^${arr1}${arr2}`)
        //if(re_ex.test(str)){
        if(str.match(re_ex)){
            n++
        }
    }
    for(let i = 0; i < s.length - 1; i++){
        my_match(s.slice(i))
    }
    return n
}

其中re_ex.test(str)str.match(re_ex)均不能成功匹配,原因是字符串太长,于是使用String.startsWith()或者String.indexof()

总结:

当字符串太长时,需求也不需要匹配所有符合的子串时,应该用String.startsWith()或者String.indexof()来提高性能,String.indexof()返回匹配到第一个子串的索引值,若无匹配,则返回***-1***,返回结果为***true***和***false***