先看题目:
1.
N个数排成一排,你可以任意选择连续的若干个数,算出它们的和。问该如何选择才能使得和的绝对值最小。
如:N=8时,8个数如下:
1 2 3 4 5 6 7 8
-20 90 -30 -20 80 -70 -60 125
如果我们选择1到4这4个数,和为20,还可以选择6到8这3个数,和为-5,|-5|=5,该方案获得的和的绝对值最小。
输入格式:
第一行输入N,表示数字的个数。接下来N行描述这N个数字。
输出格式:
第一行输出一个整数,表示最小绝对值的和,第二行包含一个整数表示形成该绝对值和最长序列的长度。
1<= N<=100000
或者
2.
N个数围成一圈,要求从中选择若干个连续的数(注意每个数最多只能选一次)加起来,问能形成的最大的和。
N<=100000
这样的题目,一般可以用前缀和来做。
以第一题为例子
我们设s[i]为前i个数字之和.那么s[i]-s[j] (i>j) 就为j+1到i的数字之和。这样我们就可以任意求出一段区间的和是多少。
在利用题目的条件,看看能不能利用前缀和的性质。
还是对于第一题。我们把得到的前缀和进行排序,那么可以知道min{ abs( s[i]-s[i-1] ) }就是答案。注意排序前加入一个s[0]=0,因为s[i]-s[j] (i>j) 表示j+1到i的数字之和
因为前缀和排序后。以i为一段的区间的最小绝对值一定是 min{ abs( s[n]-s[n-1] ),abs( s[n] - s[n+1] ) } 这里的n是i在排序以后的位置
用快排nlongn就能排好,加上O(n)的扫描。
下面是自己写的第一题的代码,没有测试数据(手上的测试数据有错误)。。 大家权当参考吧