什么是滑动窗口
滑动窗口(Sliding Window)是一种用于解决数组或字符串相关问题的常用技巧。其基本思想是维护一个固定大小的窗口,通过在数组或字符串上滑动窗口的方式来求解问题。
在滑动窗口技巧中,通常需要定义两个指针,即左指针left和右指针right,来维护窗口的位置。在解决具体问题时,可以通过移动左右指针来调整窗口的大小,并根据题目要求在窗口内进行相应的操作。
滑动窗口技巧通常用于解决以下类型的问题: 1. 求解具有连续性质的子数组或子字符串的问题; 2. 求解具有固定大小的子数组或子字符串的问题; 3. 求解能够在线性时间复杂度内解决的问题。 使用滑动窗口技巧可以有效降低问题的时间复杂度,并且通常能够在O(n)的时间复杂度内解决问题。
滑动窗口与双指针关系
滑动窗口和双指针是两种常用的算法技巧,它们经常在解决数组和字符串相关问题时一起使用,或者相互结合使用。以下是滑动窗口和双指针之间的关系:
1. 滑动窗口(Sliding Window):滑动窗口是一种固定长度的窗口,在数组或字符串上从左至右移动,用于解决子串或子数组相关的问题。通过维护窗口的起始和结束位置,可以在O(n)时间复杂度内解决一些需要对连续子序列进行操作的问题。
2. 双指针(Two Pointers):双指针是指同时在数组或字符串上移动两个指针,一般有两种模式:快慢指针和左右指针。快慢指针一般用于链表相关问题,左右指针一般用于数组或字符串相关问题。在一些特定条件下,双指针可以帮助我们快速解决一些问题。
滑动窗口与双指针之间的关系包括: 1.在某些问题中,可以利用双指针来实现滑动窗口的移动。 2.滑动窗口问题中,常常使用左右指针来维护窗口的起始和结束位置。 3.双指针可以用于一些需要同时处理数组的前后两部分的问题,类似于逼近解的过程。
在一些问题中,我们可以同时使用滑动窗口和双指针技巧来解决问题,提高算法的效率和简洁性。因此,熟练掌握滑动窗口和双指针技巧,结合实际问题的特点,能够更好地解决各种算法和数据结构问题。
窗口移动的基本过程
初始化窗口与各种变量
移动窗口,移动right
满足条件后,缩小窗口,移动left
窗口的更新与维护
输出最终结果变量
举个栗子
一,【力扣LCR056】
给定一个二叉搜索树的 根节点 root
和一个整数 k
, 请判断该二叉搜索树中是否存在两个节点它们的值之和等于 k
。假设二叉搜索树中节点的值均唯一。
一个很明显直接的方法则是将二叉树进行排序,之后利用滑动窗口的方法
class Solution {
public:
void load_arr(TreeNode*root,vector<int>&arr){
if(! root) return;
load_arr(root->left,arr);
arr.push_back(root->val);
load_arr(root->right,arr);
}
bool findTarget(TreeNode* root, int k) {
vector<int> arr;
load_arr(root,arr);
int left=0,right=arr.size()-1;
while(left<right){
int res=arr[left]+arr[right];
if(res==k) return true;
res>k?right--:left++;
}
return false;
}
};
二,【力扣3】
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
这里利用哈希表与窗口滑动的知识能够做出来:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char,int>dic;
int res=0,len=s.size(),i=0;
for(int j=0;j<len;j++){
char cur = s[j]; // 使用 s[j] 获取字符串 s 中的字符
if(dic.find(cur) != dic.end()){ // 使用 find 方法进行检查键是否存在
i = max(dic[cur]+1,i); // 使用 max 函数比较大小
}
res = max(res,j-i+1);
dic[cur] = j; // 使用下标修改 Map 中的值
}
return res;
}
};