共计 1829 个字符,预计需要花费 5 分钟才能阅读完成。
题目:给定一个字符串 s,计算具有相同数量 0 和 1 的非空 (连续) 子字符串的数量,并且这些子字符串中的所有 0 和所有 1 都是组合在一起的。重复出现的子串要计算它们出现的次数。
输入: "00110011"
输出: 6
解释: 有 6 个子串具有相同数量的连续 1 和 0:“0011”,“01”,“1100”,“10”,“0011”和“01”。请注意,一些重复出现的子串要计算它们出现的次数。另外,“00110011”不是有效的子串,因为所有的 0(和 1)没有组合在一起。来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/count-binary-substrings
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
算法的本质是寻找规律并实现。而实现是程序 + 数据结构的结合体。规律是找到输入和输出的关系
- 寻找规律: 通过图示法发现规律所在,从上图可以看出每次匹配到的结果都是向后移一位的,所以这里可以考虑使用递归或循环处理,每次循环用当前的数字与后面的数字做比对,符合结果就返回。
所以这里我们先使把数据结构写出来,嗯,清晰很多了。
// 循环进行移位, length-1 是因为根据题意要求必须连续,最后一位数无其他可匹配对象,不可能会符合连续的要求
for (let i = 0; i < s.length - 1; i++) {
// 每次循环需要与剩余的数字进行比对,所以这里封装函数处理
let matchNUm = match(s.slice(i))
if (matchNUm) arr.push(matchNUm)
}
- 算法实现: 找出字符中数量的连续 1 和 0
// 匹配要找的子串
var match = (str) => {
// 先找出相同数量连续的 1 和 0
let j = str.match(/^(0+|1+)/)[0]
// 找出相对应的数量连续的 0 或者 1
// console.log(j) // 00、0、11、1、00、0、11
// ^ 位操作符:按位异或(XOR)对于每一个比特位,当两个操作数相应的比特位有且只有一个 1 时,结果为 1,否则为 0。(也就是取反)// 取反后需保证与 j 的个数相同,所以利用 repeat 函数做重复处理
let o = (j[0] ^ 1).toString().repeat(j.length)
// console.log(o) // 11、1、00、0、11、1、00 与 j 的值刚好相反
// 此时 j+o 便是我们要找的子串,如何进行匹配呢,使用正则处理?let reg = new RegExp(`^(${j}${o})`)
// console.log(reg, reg.test(str))
if (reg.test(str)) {return RegExp.$1}
}
整体代码
- 位操作符:参考链接
export default (s) => {var arr = [] // 用来存储匹配到的子串
/**
* 匹配要找的子串
* @param {*} str
*/
var match = (str) => {
// 先找出相同数量连续的 1 和 0
let j = str.match(/^(0+|1+)/)[0]
// 找出相对应的数量连续的 0 或者 1
// console.log(j) // 00、0、11、1、00、0、11
// ^ 位操作符:按位异或(XOR)对于每一个比特位,当两个操作数相应的比特位有且只有一个 1 时,结果为 1,否则为 0。(也就是取反)// 取反后需保证与 j 的个数相同,所以利用 repeat 函数做重复处理
let o = (j[0] ^ 1).toString().repeat(j.length)
// console.log(o) // 11、1、00、0、11、1、00 与 j 的值刚好相反
// 此时 j+o 便是我们要找的子串,如何进行匹配呢,使用正则处理?let reg = new RegExp(`^(${j}${o})`)
// console.log(reg, reg.test(str))
if (reg.test(str)) {return RegExp.$1}
}
// 循环进行移位
// length-1 是因为根据题意要求必须连续,最后一位数无其他可匹配对象,不可能会符合连续的要求
for (let i = 0; i < s.length - 1; i++) {
// 每次循环需要与剩余的数字进行比对,所以这里封装函数处理
let matchNUm = match(s.slice(i))
if (matchNUm) arr.push(matchNUm)
}
console.log('找到的子串为', arr)
return arr
}
在线运行
正文完