优选算法系列(2.滑动窗口_下)
目录
五:水果成篮(medium)
题目链接:904. 水果成篮 - 力扣(LeetCode)编辑
解法:
代码:
六:找到字符串中所有字母异位词(medium)
题目链接:438. 找到字符串中所有字母异位词 - 力扣(LeetCode)
解法:
代码:
优化:
编辑
代码:
七:串联所有单词的子串(hard)
题目链接:30. 串联所有单词的子串 - 力扣(LeetCode)
解法:
代码:
编辑
八: 最小覆盖子串(hard)
题目链接:76. 最小覆盖子串 - 力扣(LeetCode)
解法:
代码:
五:水果成篮(medium)
题目链接:904. 水果成篮 - 力扣(LeetCode)
解法:
问题可以转化为:找出一个最长的子数组满足值数组里只有不超过两种水果。
暴力解法就是利用 hash + 暴力枚举 所有子数组
思路如下:
当我们的区间rifght下一个x位置会出现第三种水果,暴力的思想我们会让left后移一位,right重走,但是如果让right回去重走到原本的位置有两种可能。
因为left少了一个水果所以如果right重新走到原来的位置kinds不可能增加所以right没必要重新走。
这样我们可以使用滑动窗口。
- 初始化哈希表 hash 来统计窗⼝内⽔果的种类和数量;
- 初始化变量:左右指针 left = 0,right = 0,记录结果的变量 ret = 0;
- 当 right 小于数组⼤小的时候,⼀直执⾏下列循环:
- 将当前水果放入哈希表中;
- 判断当前水果进来后,哈希表的⼤小:
- 如果超过 2:
- 循环结束后,ret 存的就是最终结果
代码:
C++(使用容器):
C++(用数组模拟哈希表):
java(使用容器):
java(用数组模拟哈希表):
六:找到字符串中所有字母异位词(medium)
题目链接:438. 找到字符串中所有字母异位词 - 力扣(LeetCode)
解法:
首先我们要知道我们如何去判断是否是异常位词,在相同长度的字符串我们其实可以让它们按照字典序排序之后用双指针取比较是否一样,但是排序的时间复杂度太高了。
我们也可以利用容器进行比较单词出现的次数。
那么一样的我们使用暴力思想的时候 hash1 不需要每次重新添加,只需要吧 left 出窗口的值删掉入窗口的值添加到 hash1 .
- 因为字符串 p 的异位词的⻓度⼀定与字符串 p 的⻓度相同,所以我们可以在字符串 s 中构造⼀个⻓度为与字符串 p 的⻓度相同的滑动窗口,并在滑动中维护窗口中每种字⺟的数量;
- 当窗口中每种字母的数量与字符串 p 中每种字母的数量相同时,则说明当前窗口为字符串 p 的异位词;
- 因此可以⽤两个⼤小为 26 的数组来模拟哈希表,⼀个来保存 s 中的⼦串每个字符出现的个数,另⼀个来保存 p 中每⼀个字符出现的个数。这样就能判断两个串是否是异位词。
代码:
优化:
这种解法在这里可以解决问题,但是我们这里是存的字符我们还比较好判断比较,但是如果遇到哦字符串就不好了,所以我们需要优化。
那就是利用一个count来统计窗口中“有效字符”的个数。
在这里也就是说count统计的是窗口中字符存在的个数,这里由于c的个数有两个但是p中只有一个所以count只加一次c。
到这里我们需要出窗口,但c个数是大于p中c的个数,所以出窗口的c是多余的count不用更新。
并且出窗口后窗口长度=3=count,证明这就是一个异位词。
在向后一步
在这里我们c出窗口就需要更新count了。
流程:
代码:
C++:
java:
七:串联所有单词的子串(hard)
题目链接:30. 串联所有单词的子串 - 力扣(LeetCode)
解法:
这里我们注意到words里面的每个字符串都是相同长度的,那么我们其实可以把s也分成一个个word。
我们把每⼀个单词看成⼀个⼀个字母,问题就变成了找到Γ字符串中所有的字母异词」。无非就是之前处理的对象是⼀个⼀个的字符,我们这⾥处理的对象是⼀个⼀个的单词。
那么我们这里就主要讲本题和上题(查找异位词)的不同点。
代码:
C++:
java:
八: 最小覆盖子串(hard)
题目链接:76. 最小覆盖子串 - 力扣(LeetCode)
解法:
暴力枚举+哈希表:
优化(滑动窗口+哈希表):
根据暴力枚举的思路,我们在找到一个符合要求的区间之后需要left后移,后移之后的区间有两种情况。
剩下的区间符合或者不符合要求,这两种情况right都不需要再回去。
流程:
代码:
C++:
java: