一道二进制子串算法,让面试官都解不出来?

2021/5/18 22:56:29

本文主要是介绍一道二进制子串算法,让面试官都解不出来?,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 Jeskson 程序员小灰 

图片


图片


算法题目:


给定一个字符串 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”字符。


“000111”中有多少个有效的二进制子串?

“11100”中有多少个有效的二进制子串?

“00011100”呢?


这道题目,难度系数为简单题目,涉及到的知识点为字符串。


给定函数体如下:image.png




题目理解:


通过看看这两个示例,字符串 s 给的都是二进制数,要求计算具有相同数量 0 和 1 的非空(连续)子字符串的数量,这句话里面的条件有三个:


第一 不为空,非空(连续)


第二 0 和 1 是要相同数量的


第三 0 和 1 要是连续出现的子字符串的数量


描述:


如果遇到10或者是01的情况,则说明连续的1或者是连续的0断了,那么可以拿到前面连续1或者是连续0的数量,然后再查找后面连续1或者是连续0的数量,作比较看看有多少个符合的子串。


多种解题思路:


我看到这个题之后,想起来好几种解法,都写下来可能篇幅较长,如果只是简单罗列可能不太好找,就做了这个目录导图,可以对照目录图去看。


图片


第一种JavaScript方法:按照前后数量判断:


"1100"中有1和0的数量相等则有两个符合的子串


“11000”,“0000111”中,1和0的数量不相等,则有:


min(1的数量,0的数量)个符合的子串。


如果遇到10或者是01的情况,则说明连续的1或者是连续的0都断了,那么就可以拿到前面连续1或者是0的数量了,然后在往后找连续的0或者是1的数量。接着看看有多少个符合的子串,之后持续向后查找。


image.pngimage.png


看完代码得知,返回count,循环字符串从1,开始,如果s[1]

不等于前一个数,即可能是01,或者是10的情况下,那么前面的数量为当前1-0为1,前一个数量为1的情况,pre被赋值为i,i为1的情况。


假设情况s为:


var s = "001"


如果s[i]==s[pre]的数,s[i]=0  ,  s[pre]=0 . 


count1=0 , count2=0 . pre=0 . count=0


第二次循环,s[i]=1  ,  s[pre]=0 . 两者是不相等的,所以有


s[i] !== s[pre]为true,此时count1为0,走下面的代码块。所以结果为:


count1=2 , count2=0 . pre=2 . count=0


因为最后了i === s.length - 1这种情况成立,所以输出结果为


count1=2 , count2=1 . pre=2 . count=1image.png


image.png


其实可以看出代码中一开始都会走count1===0这条路线。pre为递增下标数,比较当前值与前一个值的情况。每次(pre=i)


image.png

image.png


看图带入,解释一下,本质,如果循环中两者不相等

(s[i] !== s[pre])走里面的情况,如果前者和后者比较为相等情况,不走if(s[i] !== s[pre])里的代码块,知道不相等的情况。最后一个数到了最后即尾部,满足条件(i === s.length - 1),执行其中的代码块。image.png


image.png


image.png


image.png


第二种JavaScript方法:借助min() 方法:


JavaScript min() 方法


返回值:给定数值中最小的数。如果任一参数不能转换为数值,则返回NaN。


描述


min 是 Math 的静态方法,应该像这样使用:Math.min(),而不是作为你创建的 Math 实例的方法(Math 不是构造函数)。


如果没有参数,结果为Infinity。如果有任一参数不能被转换为数值,结果为 NaN。


什么是JavaScript Math 对象?


定义和用法


min() 方法可返回指定的数字中带有最低值的数字。


Math.min.apply(null, arr)


var array=[2,6,5,8,7];Math.min.apply(null,array);


image.png


image.png


如果第一数与第二个数相等,比如00,current就要加+1的情况,当前的数量从1变为了2。如果为01,当前的数量给前面的数量pre,当前数量current为1。min取得是数量,pre,current。

image.png

image.png

image.png


第三种JavaScript方法:借助min() 方法与push() 方法:


total为计数,res存储相邻连续字符串的个数


JavaScript push() 方法


定义和用法

push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。


语法


arrayObject.push(newelement1,newelement2,....,newelementX)


newelement1必需。要添加到数组的第一个元素。
newelement2可选。要添加到数组的第二个元素。
newelementX可选。可添加多个元素。


返回值


把指定的值添加到数组后的新长度。


push() 方法可把它的参数顺序添加到 arrayObject 的尾部。它直接修改 arrayObject,而不是创建一个新的数组。push() 方法和 pop() 方法使用数组提供的先进后出栈的功能。


image.png


如何使用 min() 来返回指定数字中带有最低值的数字:image.png


输出:image.png




第四种JavaScript方法:借助match() 方法image.png



  • 000111必定有三个子串

  • 00011必定有两个子串

  • 0111必定有1个子串


以此类推, 每两组数据之间长度最短的值为子串的数量

把字符串按数字分组切割,如:['00', '11', '00', '11']

但是如果 是 1010100 这种,怎么解释才合理呢?


解题思路:


把字符串按数字分组切割,如:['00', '11', '00', '11'],相邻的两组数据组合,长度较短的数据长度即为这组数据可能的数据次数

image.png


定义和用法


match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。


该方法类似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置。


返回值


存放匹配结果的数组。image.png

第五种JavaScript方法:通用方法

image.png

image.png看了代码解析应该是懂的了,不过在这里还是口述一下下。


满是条件为01或者是10,就是两者不同,计数加1,出现001,或者是110的情况下,为前面2个0,后面1个1,前面的数量大于后面的数量即为满足一次条件,110的情况也是如此,1的数量为2,0的数量为1。


那么我们来定义一个变量let pre这个变量,这个变量的意思为计算前一个字符串出现的次数,首先这个变量的初始化值为0。如果当前数为 1,那么前面就没有数字,即为它的数量为0。


这里我们需要设置当前数量为1,即出现一个数字,那么数量即为1个。满足条件为前面的数量大于等于后面的数量,即为pre>=cur时,我们计数满足条件加1的情况,定义计数为count,满足条件时,count++image.png




注意:计算前一个字符连续出现的次数和计算后一个字符连续出现的次数不同哦!


然后我们给定一个字符串数字,“00110011”,我们需要循环这个字符串中的数字,比较前一个数字和后一个数字是否相等,如果相等,是什么情况呢?如:00或者是11的情况下,当前数cur就要加1。


如果出现不一样的字符时,即情况:10或者是01这些情况,那么计算前一个字符连续出现的次数从0变为1,它有数字,即开始有次数了。把当前cur的次数赋值给pre(计算前一个字符连续出现的次数)。看着01和10的情况,当前cur的次数赋值为1。


满足条件,有人问了,那么001的情况或者是110或者是1100或者是0011或者是111000或者是000111或者是1010等情况下呢?


即这些情况满足如下:计算前一个字符连续出现的次数大于等于计算后一个字符连续出现的次数,即为pre>=cur的条件下满足,计数情况count++,循环字符串后,返回我们需要的count计数。


写在最后


好了,本章已结束,本质上就是用法不同,解法不同而已!多多打印理解即可!


感谢阅读,原创不易,喜欢就点个[在看] or [转发朋友圈],这是我写作最大的动力。


最后,小灰非常欢迎大家在本公众号上投稿,有意向的小伙伴可以在公众号后台回复 “投稿” 两个字。




—————END—————




这篇关于一道二进制子串算法,让面试官都解不出来?的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程