【滑动窗口、双指针、单调队列】5.7任务

滑动窗口、双指针、单调队列

Leetcode.167两数之和 II - 输入有序数组 (so easy~)
Leetcode.88合并两个有序数组 (还行)
Leetcode.26删除有序数组中的重复项 (写的比我好)
Leetcode.76最小覆盖子串 (不瞒说,再做一遍还是不会)
Leetcode.32最长有效括号 (思路很牛逼,再做一遍还是不会)
Leetcode.155最小栈 (还是思路牛逼!!!)
Leetcode.42接雨水 (用的是最朴素的方法)
Leetcode.84柱状图中最大的矩形
Leetcode.239滑动窗口最大值
Leetcode.918环形子数组的最大和

一、Leetcode.167两数之和 II - 输入有序数组

给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。

以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。

你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

你所设计的解决方案必须只使用常量级的额外空间。

  vector<int> twoSum(vector<int>& numbers, int target) {
        int i=0,j=numbers.size()-1;
        while(i<j){
            if(numbers[i]+numbers[j]==target)return {i+1,j+1};
            else if(numbers[i]+numbers[j]>target)j--;
            else i++;
        }
        return{-1,-1};
    }

二、Leetcode.88合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

  void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int i=m-1,j=n-1,k=m+n-1;
        while(i>=0&&j>=0){
            if(nums1[i]>nums2[j])nums1[k--]=nums1[i--];
            else nums1[k--]=nums2[j--];
        }
        while(j>=0)nums1[k--]=nums2[j--];
        return;
    }

三、Leetcode.26删除有序数组中的重复项

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

  int removeDuplicates(vector<int>& nums) {
        if(nums.empty())return 0;
        int k=1;
        for(int j=1;j<nums.size();j++){
            if(nums[j]!=nums[k-1]){
                nums[k]=nums[j];
                k++;
            }
        }
        return k;
    }

四、Leetcode.76最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。

  unordered_map<char,int>sm,tm;
    string ans="";
    string minWindow(string s, string t) {
        for(int i=0;i<t.size();i++)
            tm[t[i]]++;
        int cnt=0;
        int k=0;
        for(int i=0;i<s.size();i++){
            sm[s[i]]++;
            if(sm[s[i]]<=tm[s[i]])cnt++;
            while(k<=i&&sm[s[k]]>tm[s[k]]){
                sm[s[k++]]--;
            }
            if(cnt==t.size()){
                if(ans.empty()||ans.size()>i-k+1)
                    ans=s.substr(k,i-k+1);
            }
        }
        return ans;
    }

五、Leetcode.32最长有效括号

给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

  int work(string s){
        int start=0;
        int cnt=0;
        int ans=0;
        for(int i=0;i<s.size();i++){
            if(s[i]=='(')cnt++;
            else cnt--;
            if(cnt<0){start=i+1;
            cnt=0;
            }
            else if(cnt==0)ans=max(ans,i-start+1);
        }
        return ans;
    }
    int longestValidParentheses(string s) {
        int ans1=work(s);
        reverse(s.begin(),s.end());
        for(auto &c:s)c^=1;
        int ans2=work(s);
        return max(ans1,ans2);
    }

六、Leetcode.155最小栈

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

  stack<int>st,st_min;
    MinStack() {

    }
    
    void push(int val) {
        st.push(val);
        if(st_min.empty())st_min.push(val);
        else st_min.push(min(st_min.top(),val));
    }
    
    void pop() {
        st.pop();
        st_min.pop();
    }
    
    int top() {
        return st.top();
    }
    
    int getMin() {
        return st_min.top();
    }

七、Leetcode.42接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

  int trap(vector<int>& height) {
        int n=height.size();
        vector<int>left(n),right(n);
        left[0]=height[0];
        for(int i=1;i<height.size();i++){
            left[i]=max(left[i-1],height[i]);
        }
        right[height.size()-1]=height[height.size()-1];
        for(int i=height.size()-2;i>=0;i--){
            right[i]=max(right[i+1],height[i]);
        }
        int ans=0;
        for(int i=0;i<height.size();i++){
            ans+=min(left[i],right[i])-height[i];
        }
        return ans;

    }

八、Leetcode.84柱状图中最大的矩形

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

  stack<int>stack;
    int largestRectangleArea(vector<int>& heights) {
        int n=heights.size();
        vector<int>left(n),right(n);
        for(int i=0;i<heights.size();i++){
            while(!stack.empty()&&heights[stack.top()]>=heights[i])stack.pop();
            if(stack.empty())left[i]=-1;
            else  left[i]=stack.top();
            stack.push(i);
        }
        while(!stack.empty())stack.pop();
        for(int i=heights.size()-1;i>=0;i--){
            while(!stack.empty()&&heights[stack.top()]>=heights[i])stack.pop();
            if(stack.empty())right[i]=heights.size();
            else  right[i]=stack.top();
            stack.push(i);
        }
        int ans=0;
        for(int i=0;i<heights.size();i++)
            ans=max(ans,heights[i]*(right[i]-left[i]-1));
        return ans;
    }

九、Leetcode.239滑动窗口最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 。

  vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int>ans;
        deque<int>q;
        for(int i=0;i<nums.size();i++){
            if(q.size()&&q.front()+k<=i)q.pop_front();
            while(q.size()&&nums[q.back()]<=nums[i])q.pop_back();
            q.push_back(i);
            if(i-k>=-1)ans.push_back(nums[q.front()]);
        }
        return ans;
    }

十、Leetcode.918环形子数组的最大和

给定一个长度为 n 的环形整数数组 nums ,返回 nums 的非空 子数组 的最大可能和 。

环形数组 意味着数组的末端将会与开头相连呈环状。形式上, nums[i] 的下一个元素是 nums[(i + 1) % n] , nums[i] 的前一个元素是 nums[(i - 1 + n) % n] 。

子数组 最多只能包含固定缓冲区 nums 中的每个元素一次。形式上,对于子数组 nums[i], nums[i + 1], …, nums[j] ,不存在 i <= k1, k2 <= j 其中 k1 % n == k2 % n 。

  int maxSubarraySumCircular(vector<int>& nums) {
        int n=nums.size();
        vector<int>sum(2*n+1,0);
        for(int i=1;i<sum.size();i++){
            if(i<=nums.size())
                sum[i]=sum[i-1]+nums[i-1];
            else sum[i]=sum[i-1]+nums[i-n-1];
        }
        deque<int>q;
        q.push_back(0);
        int ans=nums[0];
        for(int i=1;i<=2*n;i++){
            while(q.size()&&q.front()+n<i)q.pop_front();
            ans=max(ans,sum[i]-sum[q.front()]);
            while(q.size()&&sum[q.back()]>=sum[i])q.pop_back();

            q.push_back(i);

        }
        return ans;
        
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值