滑动窗口与双指针

什么是滑动窗口

        滑动窗口(Sliding Window)是一种用于解决数组或字符串相关问题的常用技巧。其基本思想是维护一个固定大小的窗口,通过在数组或字符串上滑动窗口的方式来求解问题。

         在滑动窗口技巧中,通常需要定义两个指针,即左指针left和右指针right,来维护窗口的位置。在解决具体问题时,可以通过移动左右指针来调整窗口的大小,并根据题目要求在窗口内进行相应的操作。

        滑动窗口技巧通常用于解决以下类型的问题: 1. 求解具有连续性质的子数组或子字符串的问题; 2. 求解具有固定大小的子数组或子字符串的问题; 3. 求解能够在线性时间复杂度内解决的问题。 使用滑动窗口技巧可以有效降低问题的时间复杂度,并且通常能够在O(n)的时间复杂度内解决问题。

滑动窗口与双指针关系

        滑动窗口和双指针是两种常用的算法技巧,它们经常在解决数组和字符串相关问题时一起使用,或者相互结合使用。以下是滑动窗口和双指针之间的关系:

1. 滑动窗口(Sliding Window):滑动窗口是一种固定长度的窗口,在数组或字符串上从左至右移动,用于解决子串或子数组相关的问题。通过维护窗口的起始和结束位置,可以在O(n)时间复杂度内解决一些需要对连续子序列进行操作的问题。

2. 双指针(Two Pointers):双指针是指同时在数组或字符串上移动两个指针,一般有两种模式:快慢指针和左右指针。快慢指针一般用于链表相关问题,左右指针一般用于数组或字符串相关问题。在一些特定条件下,双指针可以帮助我们快速解决一些问题。

        滑动窗口与双指针之间的关系包括: 1.在某些问题中,可以利用双指针来实现滑动窗口的移动。 2.滑动窗口问题中,常常使用左右指针来维护窗口的起始和结束位置。 3.双指针可以用于一些需要同时处理数组的前后两部分的问题,类似于逼近解的过程。

        在一些问题中,我们可以同时使用滑动窗口和双指针技巧来解决问题,提高算法的效率和简洁性。因此,熟练掌握滑动窗口和双指针技巧,结合实际问题的特点,能够更好地解决各种算法和数据结构问题。

窗口移动的基本过程

38567f85b8d54099a99d43387f035894.png

f7853a6b06694dab9b3267645f711c56.png 

初始化窗口与各种变量

移动窗口,移动right

满足条件后,缩小窗口,移动left

窗口的更新与维护

输出最终结果变量

举个栗子

一,【力扣LCR056】

        给定一个二叉搜索树的 根节点 root 和一个整数 k , 请判断该二叉搜索树中是否存在两个节点它们的值之和等于 k 。假设二叉搜索树中节点的值均唯一。

 a386017bd42141598d7fa5441bf1b2c6.png

一个很明显直接的方法则是将二叉树进行排序,之后利用滑动窗口的方法


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 ,请你找出其中不含有重复字符的 最长子串 的长度。

927cecf958b54b2584b27714299b8538.png

这里利用哈希表与窗口滑动的知识能够做出来:

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;
    }
};

 

 

  • 23
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值