刷题心得4——尺取

尺取

最经典的尺取题:

3061 – Subsequence (poj.org)

题目描述

给定一个长度为 N 的正整数序列(10 < N < 100 000),序列中的每个数字都小于等于 10000,以及一个正整数 S(S < 100 000 000)。编写一个程序,找到序列中长度最小的连续子序列,其元素和大于或等于 S。

输入

第一行是测试用例的数量。对于每个测试用例,程序需要从第一行读取数字 N 和 S,数字之间用空格分隔。第二行是该测试用例的序列数字,数字之间用空格分隔。输入以文件结束符结束。

输出

对于每个测试用例,程序需要在输出文件的单独一行打印结果。如果没有符合条件的子序列,输出 0。

样例输入

10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5

样例输出

3

思路:找满足条件的最小区间,尺取

代码:

#include <iostream>
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int main(){
	int t;
	cin>>t;
	while(t--){
		int n,m;
		cin>>n>>m;
		for(int i=0;i<n;i++){
			cin>>a[i];
		}
		int l=0,r=0,ans=1e5+5,sum=0;
		while(1){
			while(sum<m&&r<n){
				sum+=a[r++];
			}
			if(sum<m) break;
			while(sum>=m&&l<r){
				ans=min(ans,r-l);
				sum-=a[l++];
			}
		}
		if(ans==1e5+5) cout<<0<<endl;
		else cout<<ans<<endl;
	}
	return 0;
} 

第二道是力扣的一道困难题:76. 最小覆盖子串 - 力扣(LeetCode)

但也是找最小区间,尺取解决

代码:

class Solution {
public:
    string ss,tt;
    int num_t[100];
    bool is_Bao(int num_s[]){ //怎么用快速的方法判断区间是否满足条件
        for(int i=0;i<80;i++){
            if(num_s[i]<num_t[i])
                return false;
        }
        return true;
    }
    string minWindow(string s, string t) {//找最小子串:那么就是尺取
        int num_s[100];
        for(int i=0;i<100;i++) num_s[i]=0;

        //使用hash
        int m=s.length();
        int n=t.length();

        long long right_ans=0;
        for(int i=0;i<n;i++) num_t[t[i]-'A']++;
        int l=0,r=0;
        int minLen = 1e5+5;
        int ans_l=0,ans_r=0;
    
        while(1){
            while(!is_Bao(num_s)&&r<m){
                num_s[s[r]-'A']++;
                r++;
            }
            if(!is_Bao(num_s)) break;
            while(is_Bao(num_s)&&l<r){
                if(r-l<minLen){
                    minLen=r-l;
                    ans_l=l;
                    ans_r=r;
                }
                num_s[s[l]-'A']--;
                l++;
            }
        }
        string ans="";
        for(int i=ans_l;i<ans_r;i++){
            ans+=s[i];
        }
        return ans;
    }
};
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值