携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情 >>
一、基础知识
-
为什么我们要用它:
- 针对特定问题,减少复杂度,从两次循环遍历优化成一次循环遍历。
-
什么是窗口:
- 连续的子项,重点是连续。
- 滑动窗口算法会用到左右两个指针,中间的部分就是窗口。窗口可以伸缩、扩张,也可以平移。
- 滑动的是什么:左右指针
- 捕捉到什么关键词我可以用滑动窗口?:正如1中所说,当察觉到题目中的判定条件是针对一个连续的区间的时候,可以考虑滑动窗口进行解法。
-
那滑动窗口到底是什么?
- 第一步
-
第二步
-
第三步
二、模板篇
综上所述,可以抽象出一个代码模板:
function swipe(arr) {
let result = 0
let left = 0
let right = 1
while (left < arr.length - 1) {
while (right < arr.length + 1) {
if (// 满足某种条件之后) {
right++
} else {
break
}
}
left ++
// 也可能不是+1,根据题目来定
right = left + 1
}
return result
}
三、题目解析篇
这次要解的两个题目是:1004. 最大连续1的个数 III,3. 无重复字符的最长子串,都是比较典型的题目。
题解里有许多优秀的解法,我的时间复杂度和空间复杂度都不是最棒的那一波,但是我认为是相对好理解的那一波,哈哈。
1004. 最大连续1的个数 III
给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。
示例 1:
输入:nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。
示例 2:
输入:nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。
提示:
1 <= nums.length <= 105
nums[i] 不是 0 就是 1
0 <= k <= nums.length
来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
- 先读题,需要的是“数组中连续1的最大个数”,那么可以考虑滑动算法的解法。
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var longestOnes = function(nums, k) {
// 边界条件容错
if (!nums.length) return 0
// 简化边界条件计算量 start,但也增加了耗时
const initZeroList = nums.filter(num => num === 0)
if (initZeroList.length <= k) return nums.length
// 简化边界条件计算量 end
let left = 0
let right = 1
let max = 0
// 模板代码部分
while (left < nums.length - 1) {
while (right < nums.length + 1) {
// 简化,不符合条件的直接过掉
if (right - left <= max) {
right ++
continue
}
const zeroList = nums.slice(left, right).filter(num => num === 0)
if (zeroList.length <= k) {
max = right - left
right ++
} else {
break
}
}
left ++
right = left + max
}
return max
};
3. 无重复字符的最长子串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
同样画关键词,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串,所以继续考虑滑动窗口。
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function (s) {
if (!s) return 0;
if (s.length === 1) return 1;
// 通过hashmap来判断是否有重复
function hasRepeat(arr) {
const hash = {};
for (let i = 0; i < arr.length; i++) {
if (hash[arr[i]]) {
return true;
}
hash[arr[i]] = true;
}
return false;
}
// 模板代码开始
let max = 0;
const sArr = s.split("");
let left = 0;
let right = 1;
while (left < sArr.length - 1) {
while (right < sArr.length + 1) {
if (right - left < max) {
right++;
continue;
}
if (!hasRepeat(sArr.slice(left, right))) {
max = right - left;
right++;
} else {
break;
}
}
left++;
right = left + max;
}
return max;
};
这是我的小白学算法系列第一篇