1044 Shopping in Mars

大致题意就是给定N个数,找出满足第i个数到第j个数的和SUM等于M(如果找不到,也可以找SUM-M>0差值最小)的i和j,并输出i-j。

思路:可以使用数组SUM[i]存放1到i的和,这样i到j的和可以写成SUM[j]-SUM[i-1]。

这题可以用二分法做,但是二分法边界值条件太多,容易出错,推荐使用two pointers。这题用的是two pointers同向扫描法,固定左边界,移动右边界直到不满足某种条件后再移动左边界,终止条件是右边界达到数组末端。

第一次使用two pointers找出最小差值MIN

第二次使用two pointers,如果满足差值MIN==SUM[j]-SUM[i-1],那么输出i-j

#include"iostream"
using namespace std;

int  sum[200010] = {0};//sum[0] = 0
int main() {
    int  n,m;
    scanf("%d%d",&n,&m);
    for(int i = 1 ; i <= n; ++i) {
        scanf("%d",&sum[i]);
        sum[i]+= sum[i-1];
    }
    int i = 1,j = 1,MIN = 0x3fffffff;
    //达到数组右端时结束循环,此时再移动左边界也无法满足条件了
    while(j <= n) {//two pointers同向扫描,找出最小差值 MIN 
        while(j<=n && sum[j] - sum[i-1] < m)
            j++;
        if(j <=n && MIN >= sum[j]-sum[i-1]-m) {
            MIN = sum[j]-sum[i-1]-m;
        }
        i++;
    }
    i = 1,j = 1;
    while(j <= n) {//再次two pointers同向扫描,如果差值MIN==sum[j]-sum[i],则输出两个端点i+1,j
        while(j<=n && sum[j] - sum[i-1] < m)
            j++;
        if(j <= n && MIN == sum[j]-sum[i-1]-m) {
            printf("%d-%d\n",i,j);
        }
        i++;
    }
    return 0;
}

 

posted @ 2020-02-12 12:25  tangq123  阅读(144)  评论(0编辑  收藏  举报