算法:2.双指针变式 滑动窗口(c/c++ python 板)
·
一.说明
1.本代码部分注释均来自于ai
2.建议了解原理后,再去写题目,不要直接看解析
2.何为滑动窗口:

2练习
1.题目: 长度最小数组

1.c++/c
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
// n:数组nums的长度
int n = nums.size();
// l:滑动窗口左指针;r:滑动窗口右指针(初始均为0)
int l = 0; int r = 0;
// ret:记录满足条件的最短子数组长度,初始化为INT_MAX(整数最大值)
int ret = INT_MAX; // 使ret值为最大
// sum:记录当前滑动窗口内元素的和
int sum = 0;
// 右指针r遍历数组,扩展窗口右边界
for (r = 0; r < n; ++r) {
// 将当前右指针元素加入窗口和
sum += nums[r];
// 当窗口和>=target时,尝试收缩左指针以寻找更短的有效窗口
while (sum >= target) {
// 更新最短长度:当前窗口长度(r-l+1)与历史最小值比较
ret = min(ret, r - l + 1);
// 左指针右移,从窗口中移除左元素,减小窗口和
sum -= nums[l];
l += 1;
}
}
// 若未找到有效窗口(ret仍为INT_MAX),返回0;否则返回最短长度
return ret == INT_MAX ? 0 : ret;
}
};
2.python
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
# n:数组nums的长度
n = len(nums)
# l:滑动窗口左指针;r:滑动窗口右指针(初始均为0)
l = 0;r=0
# ret:记录满足条件的最短子数组长度,初始化为无穷大(用于后续比较更新)
ret = float("inf") # 使ret值为最大
# sum:记录当前滑动窗口内元素的和
sum = 0
# 右指针r遍历数组,扩展窗口右边界
for r in range(0,n):
# 将当前右指针元素加入窗口和
sum+=nums[r]
# 当窗口和>=target时,尝试收缩左指针以寻找更短的有效窗口
while sum>=target:
# 更新最短长度:当前窗口长度(r-l+1)与历史最小值比较
ret=min(ret,r-l+1)
# 左指针右移,从窗口中移除左元素,减小窗口和
sum-=nums[l]
l+=1
# 若未找到有效窗口(ret仍为无穷大),返回0;否则返回最短长度
return 0 if ret==float("inf") else ret
2.无重复的最长子串
分析:

1.c++/c
/*class Solution {
public:
int lengthOfLongestSubstring(string s) {
// n:字符串长度;l:左指针(窗口左边界的前一位,初始为-1)
int n = s.size(); int l = -1;
// long1:记录最长无重复子串的长度;temp:存储当前字符的ASCII码
int long1 = 0; int temp = 0;
// 哈希数组:大小150(覆盖ASCII字符),初始值-1(标记字符未出现)
vector<int> hash(150, -1);
// 右指针r遍历字符串,扩展窗口右边界
for (int r = 0; r < n; r++) {
// 获取当前字符的ASCII码(C++中char直接转换为整数)
temp = s[r];
// 若当前字符已在窗口内(哈希值为1),收缩左指针
while (hash[temp] == 1) {
l++; // 左指针右移
hash[s[l]] = -1; // 重置左指针经过字符的哈希状态
}
// 标记当前字符已加入窗口(哈希值设为1)
hash[temp] = 1;
// 更新最长子串长度(当前窗口长度为r - l)
long1 = max(long1, r - l);
}
return long1;
}
};*/
//优化版
class Solution {
public:
int lengthOfLongestSubstring(string s) {
// n:字符串长度;l:左指针(窗口左边界的前一位,初始为-1)
int n = s.size(); int l = -1;
// long1:记录最长无重复子串的长度
int long1 = 0;
// 哈希数组:大小150(覆盖ASCII字符),初始值-1(标记字符未出现)
vector<int> hash(150, -1);
// 右指针r遍历字符串,扩展窗口右边界
for (int r = 0; r < n; r++) {
// 获取当前字符的ASCII码,作为哈希数组索引
int temp = s[r];
// 若当前字符已出现且上次位置在窗口内,左指针跳至上次位置
if (hash[temp] > l) {
l = hash[temp];
}
// 更新当前字符的最新出现位置(右指针r)
hash[temp] = r;
// 更新最长子串长度(当前窗口长度为r - l)
long1 = max(long1, r - l);
}
return long1;
}
};
2.python
"""class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# n:获取字符串s的长度;l:左指针,初始值-1(窗口左边界的前一位)
n=len(s);l=-1
# long:存储最长无重复子串的长度(结果变量);temp:临时存储当前字符的ASCII码
long=0;temp=0
# 哈希数组:大小150(覆盖ASCII字符范围),初始值-1(标记字符未出现)
hash=150*[-1]
# 右指针r从0遍历到n-1,逐步扩展窗口右边界
for r in range(0,n):
# 计算当前右指针指向字符的ASCII码,存入temp
temp=ord(s[r])
# 若当前字符已在窗口内(hash[temp] == 1),循环收缩窗口
while(hash[temp]==1):
l+=1 # 左指针右移,缩小窗口
hash[ord(s[l])]=-1 # 重置左指针经过字符的哈希状态(标记为未出现)
# 标记当前字符已加入窗口(哈希值设为1)
hash[temp]=1
# 计算当前窗口长度(r-l),更新最长长度long
long=max(long,r-l)
# 返回最长无重复子串的长度
return long
"""
#优化版
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# n:字符串s的长度;l:左指针,初始值-1(窗口左边界的前一位)
n=len(s);l=-1
# long:存储最长无重复子串的长度(结果变量)
long=0
# 哈希数组:大小150(覆盖ASCII字符范围),初始值-1(标记字符未出现)
hash=150*[-1]
# 右指针r从0遍历到n-1,扩展窗口右边界
for r in range(0,n):
# 计算当前字符的ASCII码,存入temp(避免重复调用ord函数)
temp=ord(s[r])
# 若当前字符已出现过,且上次出现位置在当前窗口内(>l),左指针直接跳到该位置
if hash[temp]>l:
l=hash[temp]
# 更新当前字符的最新出现位置(当前右指针r)
hash[temp]=r
# 计算当前窗口长度(r-l),更新最长长度long
long=max(long,r-l)
# 返回最长无重复子串的长度
return long
二:练习
1.最大连续1的个数 III
2.1658. 将 x 减到 0 的最小操作数
3.904. 水果成篮
4.438. 找到字符串中所有字母异位词
更多推荐


所有评论(0)