基础算法(蓝桥杯)--无敌的双指针

B站视频链接:A18 双指针(尺取法)_哔哩哔哩_bilibili

双指针算法:

 

1、题目:输入一串字符串(有空格),输出用空格隔开的每段字符串.

例:输入abc def gh

       输出:abc

                  def

                  gh

#include <bits/stdc++.h>
using namespace std;

char s[1010];


int main(){
	while(~scanf("%s",s))puts(s);//一行搞定输入
	int n=strlen(s),j;
	for(int i=0;i<n;i++){//i为快指针 
		while(j<n&&s[j]!=' ')j++;//j为快指针
		for(int k = i; k < j; k++ )printf("%c", s[i]);
		i=j;// 一段结束后快慢指针指向同一位置 
	} 
	return 0;
}

2、题目:数组的目标和

#include <bits/stdc++.h>
using namespace std;

const int N = 100010;

int n, m;
int a[N], b[N];

int main()
{
    int x;
    cin >> n >> m >> x;
    for(int i = 0; i < n; i++) scanf("%d", &a[i]);
    for(int i = 0; i < m; i++) scanf("%d", &b[i]);
    //a从小到大枚举,b从大到小枚举,即两头往中间走 
    for(int i = 0, j = m - 1; i < n && j >= 0 ; i++){
        while(a[i] + b[j] > x) j--;//大于x, b往前(j指针往左)移动
        
        if(a[i] + b[j] == x) 
        {
            printf("%d %d", i, j);
            break;
        }
    }
    
    return 0;
}

3、判断子序列

#include <bits/stdc++.h>
using namespace std;

const int N = 100010;

int n, m;
int p[N], s[N];
int cnt;

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i++) scanf("%d", &p[i]);
    for(int i = 0; i < m; i++) scanf("%d", &s[i]);
    
    int cnt = 0;
    for(int i = 0; i < m; i ++)//i为p子序列指针, j为s序列指针
    {
        if(cnt < n && s[i] == p[cnt]) cnt ++;//匹配成功就让i ++
        //但是可以把判断条件改成 cnt >= n即匹配成功全部都有 : p的元素s都有
    }
    
    if(cnt >= n) puts("Yes");  //cnt >= n说明全部都有, 大于n说明有重复的 : 前面加上cnt < n的限制则cnt最大为n    
    else puts("No");
    
    return 0;
}

4、题目链接:连续自然数和 - 洛谷 

#include <bits/stdc++.h>
using namespace std;

int main(){
	int m;
	scanf("%d",&m);
	int i,j,sum=1;
	while(i<=m/2){//因为至少两个数 
		if(sum<m){
			j++;
			sum+=j;
		}
		if(sum>=m){
			if(sum==m)printf("%d %d\n",i,j);
			sum-=i;
			i++;
		}
	}
	
	return 0;
}

 5、A-B数对

#include <bits/stdc++.h>
using namespace std;

const int N=2e5+10;
int n,c,a[N];

int main(){
	cin>>n>>c;
	for(int i=1;i<=n;i++)cin>>a[i];
	sort(a+1,a+1+n);//变成有序序列
	 
	long long ans=0;
	for(int k=1,i=1,j=1;k<=n;k++){
		while(i<=n&&a[i]-a[k]<c)i++;//左端点
		while(j<=n&&a[j]-a[k]<=c)j++;//右端点+1
		ans+=j-i; 
	}
	
	cout<<ans<<endl;
	
	return 0;
}

6、题目链接:逛画展 - 洛谷 

 

#include <bits/stdc++.h>
using namespace std;

int n,m,a[1000010];
int cnt[2010],num,len,l,r;

int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	
	cnt[a[1]]=1;
	num=1;
	len=1000010;
	for(int j=1,i=1;j<=n;){
		if(num<m){
			j++;
			cnt[a[j]]++;
			if(cnt[a[j]]==1)num++;
		}
		if(num==m){
			if(len>j-i+1){
				len=j-i+1;//更新 
				l=i;
				r=j;
			}
			cnt[a[i]]--;
			if(cnt[a[i]]==0)num--;
			i++;
		}
	}
	
	printf("%d %d\n",l,r);
	
	return 0;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值