题目:给定一个字符串 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
}
在线运行
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。