给定一个字符串 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
};
思路:

先找规律,发现适合迭代或者递归,取前几位相同的数字,然后再取反,组合成一个字符串,再去原字符串中匹配
方法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
}
思路:
暴力尝试,将所有可能的1 和0 组合都试一遍
试错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***