目录
一.题目描述
二.思路及优化
三.C++代码
一.题目描述
二.思路及优化
首先我们看到这个题,就是根据给出的数组元素个数N,从[1,N]找出N个元素,使得N个元素的和最小,其中随便抽两个数出来,两个数之和不能为target。
那我们很自然的就想到,比如N=5,那其最小和肯定是1+2+3+4+5,再给个条件说target=9,那我们会发现一件事情,4和5我们只能有一个,我们肯定舍弃5,拿个6,此时3+6=9,舍弃6,拿进来7,2+7=9,舍弃7,拿8,8+1=9,舍弃8,最后进来9,可以此时最小和是1+2+3+4+9.
根据这个思路我们就可以得到
1.大范围是[1,N]
2.如果我选了一个X在[1,N]中,那么target-x我就不能再选了。如上例:选了1就不能选8,选2就不能有7。最终两个数字慢慢向中间靠齐,得到target/2,我们是一定可以选的(因为target/2会舍弃小数,数往偏小的那边靠一些,更符合我们得到最小和)。
3.在2中我们得到,[1,target/2]我们一定如果选的话一定是最小的,但是如果是N=2,target=6这种情况呢?实际上我们选【1,2】就是最小和了。也就是说我们还需要判断N与target/2的关系。
(1.)N<=target/2.那我们直接选1到N的元素就可以了,根据等比数列前N项和得到为N(N+1)/2;
(2)如果N>target/2的话
前target/2个数我们可以选,然后再从target开始选,一直到选取的总个数到N个,即为最小和。
最小和就是 序号1的和:S1=(target/2)*(target/2+1)/2
序号2的和: 首先要知道后面有几个数:N-target/2;
那么可选数字就从target到target+(N-target/2)-1;
根据等差数列和的求和公式:
得到S2=(N-target/2)*(target+target+(N-target/2)-1)/2
最小和即为S=S1+S2
三.C++代码
题目说了对最后结果要取模,那么其和可能会有点大,我们用long long类型去存数字和;
题目所说模数为10的9次方+7.所以我们直接int mod=1e9+7;
class Solution {
public:
int minimumPossibleSum(int n, int target) {
int mod = 1e9 + 7;
int m = target / 2;
if (n <= m) {
return (long long) (1 + n) * n / 2 % mod;
}
return ((long long) (1 + m) * m / 2 +
((long long) target + target + (n - m) - 1) * (n - m) / 2) % mod;
}
};