算法练习题 1:
给定一个字符串 s
,计算具有相同数量 0 和 1 的非空(连续)
子字符串的数量,并且这些子字符串中的所有 0 和所有 1 都是组合在一起的。
重复出现的子串要计算它们出现的次数。
1. 示例 1 :
- 输入: “
00110011
” - 输出: 6
- 解释: 有 6 个子串具有相同数量的连续 1 和 0:
“0011”,“01”,“1100”,“10”,“0011” 和 “01”
。 - 请注意,一些重复出现的子串要计算它们出现的次数。
另外,“00110011”不是有效的子串,因为所有的 0(和 1)没有组合在一起
。
2. 示例 2 :
- 输入: “
10101
” - 输出: 4
- 解释: 有 4 个子串:
“10”,“01”,“10”,“01”
,它们具有相同数量的连续 1 和 0。 - 注意:
s.length 在 1 到 50,000 之间。
s 只包含“0”或“1”字符。
解题思路
通过看两个示例,字符串 s 给的都是二进制数
,要求计算具有相同数量 0 和 1 的非空(连续)
子字符串的数量,这句话里面的条件有三个
-
第一
不为空
, -
第二
0 和 1 是要相同数量的
,比如 00110011,依次执行,当第一个 1 出现时,前面已经有两个 0,所以最先出现的肯定是 01,再往后一位又是 1,这时两个 0 两个 1,就形成了 0011。。。 -
第三
0 和 1 要是连续出现的
,就比如示例中的“0011”,“01”,“1100”,“10”,“0011” 和 “01”
这些子串都是合乎要求的,但是,也有类似于“00110011”这样的,虽然也是子串,不为空,0 和 1 也同数,但是所有 0(或 1)没有组合到一起,是分散的,就不是有效符合条件的子串。 -
分析到这,我们能想到,用代码完整写出这道题,需要先
遍历字符串(for 循环)
,然后逐位 对比字符串的当前项s[i]
和后一项s[i + 1]
是否相等 ,然后相等了。。。不等。。。 -
这里至少需要三个变量:
curLen 初始为 1,记录当前 前后相同数字的数量,相等时自加
(比如 00 比时,curLen+=1,curLen 为 2)preLen 相同子串的长度
(比如 00 比时,preLen 还是初始的 0,到 01 比时,preLen 被赋予了 curLen 的值 2)result 记录成立的子串数量
/*
* @param {string} s
* @return {number}
*/
var s = "00110011"//01、0011、10、1100、01、0011成立
// var s = "10101";//10,01,10,01
console.log('s:' + s, ' s.length:' + s.length)
var countBinarySubstrings = function () {
let result = 0; //初始化为0,用来成立的子串个数
// curLen 与 preLen 分别用于记录 当前数字与下一位是否相同 、 相同子串长度
let curLen = 1;
let preLen = 0;
for (let i = 0; i < s.length - 1; i++) {
// 指针往后移动,若 当前数字 与 下一个数字 一样 则将curLen加1
if (s[i] === s[i + 1]) {
curLen += 1;
/* curLen初始值为1,s[i] === s[i + 1]?
相等 curLen=2 ,然后执行下一个if判断
不等 执行else,curLen值交予preLen,使curLen重来
*/
} else {
// 否则就是遇到了不同之处,把相同子串的长度交给preLen
// curLen 再 重新往后寻找
preLen = curLen;
curLen = 1;
}
if (preLen >= curLen) {
result += 1;
}
console.log('s[i]对比下一位s[i+1]: ' + s[i] + ' : ' + s[i + 1], ' preLen:curLen ' + preLen + ':' + curLen, ' result: ' + result, ' i取值:', i)
}
};
countBinarySubstrings()
运行结果
关于意见反馈
本号主人是个前端小白,如果有写错或者涉及不当引用等问题,烦请联系我,我一定第一时间处理!!!