给你一个整数数组 nums 和一个整数 k 。请你向 nums 中追加 k 个 未 出现在 nums 中的、互不相同 的 正 整数,并使结果数组的元素和 最小 。
返回追加到 nums 中的 k 个整数之和。
示例 1:
输入:nums = [1,4,25,10,25], k = 2
输出:5
解释:在该解法中,向数组中追加的两个互不相同且未出现的正整数是 2 和 3 。
nums 最终元素和为 1 + 4 + 25 + 10 + 25 + 2 + 3 = 70 ,这是所有情况中的最小值。
所以追加到数组中的两个整数之和是 2 + 3 = 5 ,所以返回 5 。
示例 2:
输入:nums = [5,6], k = 6
输出:25
解释:在该解法中,向数组中追加的两个互不相同且未出现的正整数是 1 、2 、3 、4 、7 和 8 。
nums 最终元素和为 5 + 6 + 1 + 2 + 3 + 4 + 7 + 8 = 36 ,这是所有情况中的最小值。
所以追加到数组中的两个整数之和是 1 + 2 + 3 + 4 + 7 + 8 = 25 ,所以返回 25 。
提示:
1 <= nums.length <= 105
1 <= nums[i], k <= 109
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/append-k-integers-with-minimal-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目思路:
先将原数组按降序排
其实看明白了题目就是用求和公式;
比如数组:nums = [5,6],插入个数:k = 6
就是要插入1--4和7,8;
1-4就等于Sn=(am+an)(n-m)/2 ==> (1+4)*4/2;
所以定义一个变量count记录am到an之间有几个; count==(n-m);
定义一个变量 j 代表am,当然 j 从 1 开始; am = j;
你应该可以看出来 an=am+count-1; an=j+count-1;
所以本题的求和公式是 : Sn = (am+an)*count/2 ==> (j+j+count-1)*count/2
==>(2*j+count-1)*count/2;
有几个注意的点就是:
1.可能数组遍历完了,k>0,所以要返回时要多求一次和
2.可能数组还没遍历完,k==0,所以count要取一个最小值count=min(nums[i]-j,k);
void swap(int q[],int i,int j)
{
int t= q[i];
q[i] = q[j];
q[j] = t;
}
void quickSort(int q[],int l,int r)
{
if(l>=r) return ;
int i=l-1,j=r+1;
int x=q[l+r>>1];
while(i<j)
{
do i++; while(q[i]<x);
do j--; while(q[j]>x);
if(i<j)
{
swap(q,i,j);
}
}
quickSort(q,l,j);
quickSort(q,j+1,r);
}
int min(int a,int b)
{
return a>b? b:a;
}
long long minimalKSum(int* nums, int numsSize, int k){
quickSort(nums,0,numsSize-1);
long long int sum=0;
long long int j=1;
for(int i=0;i<numsSize&&k;i++)
{
if(j<nums[i])
{
int count=min(nums[i]-j,k);//因为k<(nums[i]-j)的个数,所以要取最小
k-=count;
sum+=(2*j+count-1)*count/2;//求和公式
}
j=nums[i]+1;
}
return sum+(2*j+k-1)*k/2;//可能数组遍历完了,所以要返回时再求一次,反正k==0等于 sum+0
}