目录
解法⼀(暴力求解)(不会超时,可以通过):一.长度最小的子数组(medium)
题目链接·209. 长度最小的子数组 - 力扣(LeetCode)
解法:
代码:
二:无重复字符的最长⼦串(medium)
题目链接:3. 无重复字符的最长子串 - 力扣(LeetCode)
解法:
代码:
三:最大连续 1 的个数 III(medium)
题目链接:1004. 最大连续1的个数 III - 力扣(LeetCode)
解法:
代码:
四:将 x 减到 0 的最⼩操作数 (medium)
题目链接:1658. 将 x 减到 0 的最小操作数 - 力扣(LeetCode)
解法:
代码:
解法⼀(暴力求解)(不会超时,可以通过):一.长度最小的子数组(medium)
题目链接·209. 长度最小的子数组 - 力扣(LeetCode)
解法:






代码:


二:无重复字符的最长⼦串(medium)
题目链接:3. 无重复字符的最长子串 - 力扣(LeetCode)
解法:


- 右端元素 ch 进⼊窗⼝的时候,哈希表统计这个字符的频次:
- 如果这个字符出现的频次超过 1 ,说明窗⼝内有重复元素,那么就从左侧开始划出窗口, 直到 ch 这个元素的频次变为 1 ,然后再更新结果。
代码:


三:最大连续 1 的个数 III(medium)
题目链接:1004. 最大连续1的个数 III - 力扣(LeetCode)
解法:
不要去想怎么翻转,不要把问题想的很复杂,这道题的结果⽆非就是⼀段连续的 1 中间塞了 k 个 0 。 因此,我们可以把问题转化成:求数组中⼀段最长的连续区间,要求这段区间内 0 的个数不超过 k 个。
解法⼀(暴力求解):
暴力枚举+0计数器
这里就不讲暴力了。。。
解法二(滑动窗口):
在暴力求解地思路中,到这种情况时我们应该让 left++ 让 right 重新在left位置开始遍历。
但是如果这样的话我们会发现,right还是会停在之前那个位置,这是因为出窗口的数字为1并不是0,而那k个0都还在窗口里。
因此我们滑动窗口的思路就是 left 和 right 都向后走,left 走的时候要让窗口合法(也就是窗口里的0< k)时left 才停下来。
流程:
- 初始化⼀些变量 left = 0 , right = 0 , ret = 0 ;
- 当 right ⼩于数组⼤⼩的时候,⼀直下列循环:
- 让当前元素进⼊窗⼝,顺便统计到哈希表中;
- 检查 0 的个数是否超标:
- 如果超标,依次让左侧元素滑出窗⼝,顺便更新哈希表的值,直到 0 的个数恢复正常;
- 程序到这⾥,说明窗口内元素是符合要求的,更新结果;
- right++ ,处理下⼀个元素;
- 循环结束后, ret 存的就是最终结果。
代码:


四:将 x 减到 0 的最⼩操作数 (medium)
题目链接:1658. 将 x 减到 0 的最小操作数 - 力扣(LeetCode)
解法:
- 转化问题:求 target = sum(nums) - x 。如果 target < 0 ,问题⽆解;
- 初始化左右指针 l = 0 , r = 0 (滑动窗⼝区间表⽰为 [l, r) ,左右区间是否开闭很重要,必须设定与代码⼀致),记录当前滑动窗⼝内数组和的变量 sum = 0 ,记录当前满足条件数组的最⼤区间⻓度 maxLen = -1 ;
- 当 r 小于等于数组⻓度时,⼀直循环:
- 如果 sum < target ,右移右指针,直⾄变量和⼤于等于 target ,或右指针已经移到头;
- 如果 sum > target ,右移左指针,直⾄变量和⼩于等于 target ,或左指针已经移到 头;
- 如果经过前两步的左右移动使得 sum == target ,维护满⾜条件数组的最大长度,并让下个元素进入窗口
- 循环结束后,如果 maxLen 的值有意义,则计算结果返回;否则,返回 -1 。
==================== ====================
正难则反
当我们找到最合适的位置时(也就是区级和sum>=目标):
此时我们移动left,但是由于我们right前面的区间<目标值,如果right回去重新走那么依旧会白走前面的区间。。因此right没有必要再回到前面去
流程:
代码:
C++:
java: