PAT.A1044 Shopping in Mars

返回目录在这里插入图片描述

题意

给出一个数字序列与一个数m,在数字序列中求出所有和值为S的连续子序列(区间下标左端点小的先输出,左端点相同时右端点小的先输出)。若没有这样的序列,求出和值恰好大于S的子序列(即在所有和值大于S的子序列中和值最接近S)。假设序列下标从1开始。

样例(可复制)

16 15
3 2 1 5 4 6 8 7 16 10 15 11 9 12 14 13

样例输出

1-5
4-6
7-8
11-11

提供几个易错的测试数据

3 3
1 2 3
//output
1-2
3-3
3 5
2 2 2
//output
1-3
1 10
18
//output
1-1

注意点

  1. 本题可以使用二分法和two pointers解决,时间复杂度为O(nlog n)
  2. lower_bound()函数会返回查找范围内第一个大于等于指定值的数,而之前的upper_bound()函数会返回查找范围内第一个大于指定值的数;也可以不使用这两个自带的函数,自己写个二分查找函数

二分法

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

int n,m,small=INT_MAX;
int main(){
    cin>>n>>m;
    int sum[n];//存储一组数中第1个数到第i个数的和
    sum[0]=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&sum[i]);
        sum[i]+=sum[i-1];
    }
    for(int i=1;i<=n;i++){//找到small
        int j=lower_bound(sum+i,sum+n,sum[i-1]+m)-sum;
        if(sum[j]-sum[i-1]==m){
            small=m;break;
        }else if(sum[j]-sum[i-1]>m&&sum[j]-sum[i-1]<small)
            small=sum[j]-sum[i-1];
    }
    for(int i=1;i<=n;i++){//输出
        int j=lower_bound(sum+i,sum+n,sum[i-1]+m)-sum;
        if(sum[j]-sum[i-1]==small)printf("%d-%d\n",i,j);
    }
    return 0;
}

two pointers

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

int n,m,small=INT_MAX;
int main(){
    cin>>n>>m;
    int sum[n];//存储一组数中第1个数到第i个数的和
    sum[0]=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&sum[i]);
        sum[i]+=sum[i-1];
    }
    int j=1;
    for(int i=0;i<=n;i++){//找到small
        while(j<=n){
            if(sum[j]-sum[i]>=m){
                if(small>sum[j]-sum[i])small=sum[j]-sum[i];
                break;
            }
            j++;
        }
    }
    j=1;
    for(int i=0;i<=n;i++){//输出
        while(j<=n){
            if(sum[j]-sum[i]>small)break;
            if(sum[j]-sum[i]==small){
                printf("%d-%d\n",i+1,j);
                break;
            }
            j++;
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小怪兽会微笑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值