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; }