1. 问题描述:
给你一个整数数组 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 <= 10 ^ 5
1 <= nums[i],k <= 10 ^ 9
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/append-k-integers-with-minimal-sum/
2. 思路分析:
分析题目可以知道我们需要添加nums中没有出现过并且使得总和最小的k个数字,因为需要使得总和最小所以我们需要从小到大考虑这些没有出现过的数字,相当于是给我们一个数轴,数轴上有一些点,我们需要在数轴上从前往后覆盖k个没有出现过的点,所以我们可以先对nums从小到大排序,依次枚举nums中相邻的两个数字,如果他们的差值大于1说明他们之间可以填其他的数字,由于需要填k个正整数,为了方便处理我们可以将0作为边界值加入到nums中这样填的数字可以从1开始,枚举nums中相邻两个数字的时候判断他们之间可以填的数字个数是否大于等于k,如果大于等于k说明这两个端点之间的数字个数满足要求,更新一下答案break即可,不满足说明还需要枚举下一个区间,最后判断一下k是否大于0如果大于0说明区间中的数字个数小于k,还需要添加k个数字,此时从nums[-1] + 1开始填k个数字即可,可以使用等差数列求和公式求解公差为1的和。
3. 代码如下:
from typing import List
class Solution:
def minimalKSum(self, nums: List[int], k: int) -> int:
n = len(nums) + 1
# 从小到大排序
nums.sort()
# 0属于一个边界条件
nums.insert(0, 0)
res = 0
for i in range(1, n):
# 当大于的时候说明两个区间才有数字可以
if nums[i] > nums[i - 1] + 1:
# 判断两个端点处的数字的个数与k的大小关系
count = nums[i] - nums[i - 1] - 1
x = nums[i - 1] + 1
# 两个端点之间的数字个数大于k说明加上k个数字就可以了, 然后break
if count >= k:
# 使用等差数列的公式计算即可
res += (2 * x + k - 1) * k // 2
k = 0
break
# 否则加上两个端点之间的所有数字
else:
y = nums[i] - 1
res += (x + y) * (y - x + 1) // 2
k -= y - x + 1
# k大于0说明还不足k个数
if k > 0:
x = nums[-1] + 1
y = x + k - 1
res += (x + y) * k // 2
return res