[玩转算法]滑动窗口

209.Minimum Size Subarray Sum

给定一个整型数组和一个数字s,找到数组中最短的一个连续子数组使得连续子数组的数字和sum >= s,返回这个最短的连续子数组的返回值。

·如,给定数组[2,3,1,2,4,3],s = 7

·答案为[4,3],返回2

暴力解:遍历所有的连续子数组[i,j]

计算其和sum,验证sum=s;

时间复杂度O(n^3)

什么方法时间复杂度可以优化为O(n^2)

 

#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
class Solution{
public:
    //时间复杂度:O(n)
    //空间复杂度:O(1)
    int minSubArrayLen(int s,vector<int>& nums){
        int l = 0;
        int r = -1;  //nums[l...r]为滑动窗口
        int sum = 0;
        int res = nums.size() + 1;
        while(l < nums.size() ){
            if(r + 1 < nums.size() && sum < s){
                r++;
                sum += nums[r];
            }
            else{
                 sum -= nums[l++];
            }
            if(sum >= s){
                res = min(res,r-l+1);
            }
        }
        if(res == nums.size() + 1){
            return 0;
        }
        return res;
    }
    
};
int main(){
    int arr[] = {4,2,4,6,8,9,10};
    vector<int> vec(arr,arr+sizeof(arr)/sizeof(int));
    int ret = Solution().minSubArrayLen(12,vec);
    cout << ret << endl;
    return 0;
}

 

3.Longest Substring  Without Repeating Characters

在一个字符串中寻找没有重复字母的最长字串

·如“abcabcbb”,则结果为“abc”

·如“bbbb”则结果为’b’

·如“pwwkew”,则结果为“wrk”

 

#include <iostream>
#include <vector>
#include <string>
#include <cassert>
using namespace std;
class Solution{
public:
    int lengthOfLongestSubstring(string s){
        int freq[256] = {0};
        int l = 0;
        int r = -1; //滑动窗口为s[l...r]
        int res;
        while(l < s.size()){
            if(r+1 < s.size() && freq[s[r+1]] == 0){
                r++;
                freq[s[r]]++;
            }
            else{
                freq[s[l++]]--;
            }
            res = max(res, r-l+1);
        }
        return res;
    }
    
};
int main(){
    string arr = "abcabcd";
    int ret = Solution().lengthOfLongestSubstring(arr);
    cout << ret << endl;
    return 0;
}

438.Find All Anagrams in a String

给定一个字符串s和一个非空字符串p,找出P中的所有是s的anagrams字符串的子串,返回这些子串的起始索引。

·如s = “cbaebabacd”p = “abc” 返回[0,6]

·如s=”abab”,p = “ba”,返回[0,1,2]

--字符集范围?英文小写字母

--返回的解的顺序?任意

 

#include <iostream>
#include <vector>
#include <cassert>
#include <string>
using namespace std;
class Solution{
public:
    vector<int> findAnagramsstring(string nums,string target){
        assert(nums.size() > target.size());
        vector<int> sv(26,0);
        vector<int> pv(26,0);
        vector<int> res;
        for(int i = 0; i < target.size(); i++){
            ++pv[target[i] - 'a'];
            ++sv[nums[i] - 'a'];
        }
        if(sv == pv) res.push_back(0);
        for(int i = target.size(); i < nums.size();i++){
            ++sv[nums[i] - 'a'];
            --sv[nums[i - target.size()] - 'a'];
            if(pv == sv) res.push_back(i - target.size() + 1);
        }
        return res;
    }
    
};
int main(){
    string nums = "cbaebabacdcba";
    string target = "cba";
    vector<int> vec = Solution().findAnagramsstring(nums,target);
    for(int i = 0; i < vec.size(); i++){
        cout << vec[i] << " ";
    }
    cout << endl;
    return 0;
}

 

76.Minimum Window Substring

给定一个字符串S和T,在S中寻找最短的子串,包含T中的所有的字符

·如S=”ADOBECODEBANC”; T = “ABC”

·结果为“BANC”

--字符范围?

--若没有解?返回“”

--若有多个解?  保证只有一个解

--什么叫包含所有字符?S=”a”,T = “a”;

 

#include <iostream>
#include <vector>
#include <cassert>
#include <string>
using namespace std;
class Solution{
public:
    string MinWinSubstring(string src,string T){
        vector<int> Sv(256,0);
        vector<int> Tv(256,0);
        int lp = -1;
        int rp = -1;
        int answer = 0x7fffffff;
        int begin = 0;
        int lack = T.size();
        for(int i = 0; i < T.size(); i++){
            Tv[T[i]]++;
        }
        
        for(int end = 0; end < src.size(); end++){
            if(Sv[src[end]] < Tv[src[end]]){
                lack--;
            }
            Sv[src[end]]++;
            if(lack == 0){
                while(begin < end && Sv[src[begin]] > Tv[src[begin]]){
                    Sv[src[begin]]--;
                    begin++;
                }
                if(answer > end - begin + 1){
                    answer = end-begin+1;
                    lp = begin;
                    rp = end;
                }
                while(lack == 0){
                    Sv[src[begin]]--;
                    begin += 1;
                    lack += 1;
                }
            }
        }
        return lp == -1 ?" ": src.substr(lp,rp-lp+1);
    }
    
};
int main(){
    string src = "ADOBECODEBANC";
    string T = "ABC";
    string ret = Solution().MinWinSubstring(src,T);
    cout << ret << endl;
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值