feat: 添加滑动窗口相关算法209,438

This commit is contained in:
LouisFonda 2025-06-22 00:31:13 +08:00
parent 09c5a746f1
commit 614b10bcd0
Signed by: yigencong
GPG Key ID: 29CE877CED00E966
2 changed files with 173 additions and 0 deletions

View File

@ -0,0 +1,61 @@
/**
* https://leetcode.cn/problems/minimum-size-subarray-sum/?envType=study-plan-v2&envId=top-interview-150
* @param {number} target
* @param {number[]} nums
* @return {number}
*/
const minSubArrayLen = function (target, nums) {
};
/*
题目要求我们找到最短的子数组子数组就是原数组中连续的某部分我们先遍历原数组之后在遍历到的位置开始往下遍历并且求和
如果结果大于等于target就返回这个长度
*/
function f1(target, nums) {
let minLen = Infinity; // 初始化最小长度
for (let left = 0; left < nums.length; left++) {
let sum = 0; // 保存当前子数组的和
for (let right = left; right < nums.length; right++) {
sum += nums[right];
if (sum >= target) {
minLen = Math.min(minLen, right - left + 1);
// 后面匹配的结果都会符合sum>=target但是一定比当前子数组长所以直接break
break;
}
}
}
return minLen === Infinity ? 0 : minLen; // 注意清理初始化的值如果没有符合要求的返回0而不是Infinity
}
function f2(target, nums) {
let minLen = Infinity; // 初始化最小长度
let left = 0; // 滑动窗口的左边界
let sum = 0; // 滑动窗口中所有值的和
for (let right = 0; right < nums.length; right++) {
sum += nums[right];
while (sum >= target) {
minLen = Math.min(minLen, right - left + 1);
// 如果靠近right的数值很大靠近left的数值很小会造成数组长度很长所以要从左缩小窗口
sum -= nums[left];
left++;
}
}
return minLen === Infinity ? 0 : minLen; // 注意清理初始化的值如果没有符合要求的返回0而不是Infinity
}
function f3(target, nums) {
let minLen = Infinity; // 初始化最小长度
let left = 0; // 滑动窗口的左边界
let sum = 0; // 滑动窗口中所有值的和
for (let right = 0; right < nums.length; right++) {
sum += nums[right];
while (sum >= target) {
minLen = Math.min(minLen, right - left + 1);
// 如果靠近right的数值很大靠近left的数值很小会造成数组长度很长所以要从左缩小窗口
sum -= nums[left];
left++;
}
}
return minLen === Infinity ? 0 : minLen; // 注意清理初始化的值如果没有符合要求的返回0而不是Infinity
}

View File

@ -0,0 +1,112 @@
/**
* https://leetcode.cn/problems/find-all-anagrams-in-a-string/
* @param {string} s
* @param {string} p
* @return {number[]}
*/
const findAnagrams = function (s, p) {
};
/*
按照暴力解法的话我们可能会把p的所有异位词都枚举出来之后遍历遍历所有的异位词利用indexof查看每一个异位词在s中的位置如果
这个异位词在s中存在那么就把起始下标放入到结果集中如果p非常长的话那么所有异位词就是一个长度的全排列!m,加上对s的查找那就是一个
(n+m)*!m, 这显然是不能接受的所以我们需要换一种思路.
思路异位词和原词在单词数量上是一致的所以我们可以维护一个在s上长度位p.length的窗口只要这个窗口里面所有单词出现的数量和
p中所有单词出现的数量一致的话那么就认为这个窗口表示的单词是p的一个异位词最后只需把窗口的起始下标放入结果集合即可
*/
function f1(s, p) {
const result = []; // 返回的结果集
if (s.length < p.length) return result; // p比s还长在s中不可能有p的异位词直接返回
const need = new Map(); // 记录p中每一个词出现的次数用于验证异位词
const window = new Map(); // 记录当前窗口中的异位词
// 统计p的所有字符出现的次数
for (const char of p) {
need.set(char, (need.get(char) || 0) + 1);
}
let left = 0; // 滑动窗口的左边界
let right = 0; // 滑动窗口的右边界
let valid = 0; // 滑动窗口中符合异位字的字符数量;
while (right < s.length) {
const char = s[right];
if (need.has(char)) {
window.set(char, (window.get(char) || 0) + 1);
if (window.get(char) === need.get(char)) {
valid++;
}
}
// 如果窗口长度等于异位字符p的长度那么就检测当前窗口是否是一个异位词
if (right - left + 1 === p.length) {
if (valid === need.size) {
result.push(left); // 把left添加到结果集中
}
const leftChar = s[left];
// 收缩窗口
left++;
// 判断收缩掉的这个字符是否是need中的某一个字符
if (need.has(leftChar)) {
if (window.get(leftChar) === need.get(leftChar)) {
valid--; // 验证符合异位词字符个数的词减1
}
window.set(leftChar, window.get(leftChar) - 1); // 使这个字符的数量减1
}
}
// 扩展窗口
right++;
}
return result;
}
function f3(s, p) {
const result = []; // 返回的结果集
if (s.length < p.length) return result; // p比s还长在s中不可能有p的异位词直接返回
const need = new Map(); // 记录p中每一个字符出现的次数用于验证异位词
const window = new Map(); // 记录当前窗口中的异位词
// 统计p的所有字符出现的次数
for (const char of p) {
need.set(char, (need.get(char) || 0) + 1);
}
let left = 0; // 滑动窗口的左边界
let right = 0; // 滑动窗口的右边界
while (right < s.length) {
const char = s[right];
// 扩展窗口
window.set(char, (window.get(char) || 0) + 1);
// 如果当前窗口大小达到p的长度判断是否为异位词
if (right - left + 1 === p.length) {
// 比较窗口内字符的频次是否和p中一致
let isAnagram = true;
for (const [key, value] of need) {
if (window.get(key) !== value) {
isAnagram = false;
break;
}
}
if (isAnagram) {
result.push(left); // 将符合条件的起始索引加入结果
}
// 收缩窗口
const leftChar = s[left];
window.set(leftChar, window.get(leftChar) - 1); // 减少左边字符的频次
if (window.get(leftChar) === 0) {
window.delete(leftChar); // 如果频次为0移除该字符
}
left++; // 移动左指针
}
// 扩展右指针
right++;
}
return result;
}