{x}
blog image

Append K Integers With Minimal Sum

You are given an integer array nums and an integer k. Append k unique positive integers that do not appear in nums to nums such that the resulting total sum is minimum.

Return the sum of the k integers appended to nums.

 

Example 1:

Input: nums = [1,4,25,10,25], k = 2
Output: 5
Explanation: The two unique positive integers that do not appear in nums which we append are 2 and 3.
The resulting sum of nums is 1 + 4 + 25 + 10 + 25 + 2 + 3 = 70, which is the minimum.
The sum of the two integers appended is 2 + 3 = 5, so we return 5.

Example 2:

Input: nums = [5,6], k = 6
Output: 25
Explanation: The six unique positive integers that do not appear in nums which we append are 1, 2, 3, 4, 7, and 8.
The resulting sum of nums is 5 + 6 + 1 + 2 + 3 + 4 + 7 + 8 = 36, which is the minimum. 
The sum of the six integers appended is 1 + 2 + 3 + 4 + 7 + 8 = 25, so we return 25.

 

Constraints:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109
  • 1 <= k <= 108

Solution Explanation: Append K Integers With Minimal Sum

This problem asks us to append k unique positive integers to the input array nums such that the total sum of the resulting array is minimized. The solution leverages a greedy approach combined with mathematical insights for efficiency.

Core Idea:

The optimal strategy is to append the smallest possible unique positive integers that are not already present in nums. This ensures the minimum possible sum. We can efficiently find these missing integers by sorting nums and identifying gaps.

Algorithm:

  1. Handle Edge Cases and Sorting: We begin by adding two sentinel values to nums: 0 and a large number (e.g., 2 * 10^9). This simplifies the gap identification process by ensuring a gap at the beginning and end of the sorted array. Then, sort the array in ascending order.

  2. Iterate and Calculate Gaps: Iterate through the sorted nums. For each pair of adjacent elements (a, b), calculate the number of integers m missing within the gap (a+1, b-1). This is simply b - a - 1.

  3. Greedy Append and Sum Calculation: For each gap, we append the min(k, m) smallest missing integers. The sum of the x smallest consecutive positive integers starting from n is x*(n + n + x - 1)/2. We add this sum to the running total ans, and update the remaining number of integers k we need to append. If k becomes 0, we're done.

  4. Return the Sum: The final value of ans represents the sum of the appended integers.

Time and Space Complexity:

  • Time Complexity: O(n log n), dominated by the sorting step. The iteration and gap calculations are linear O(n).
  • Space Complexity: O(log n) in most implementations due to sorting (in-place sorting might use O(1) extra space).

Code Examples:

The code examples below implement this algorithm in several languages. Note the use of sentinels (0 and a large number) in each implementation. Also note that efficient arithmetic is used for sum calculation to avoid potential integer overflow issues (e.g., using long long in C++).

Python:

from itertools import pairwise
 
class Solution:
    def minimalKSum(self, nums: List[int], k: int) -> int:
        nums.extend([0, 2 * 10**9]) #add sentinels
        nums.sort()
        ans = 0
        for a, b in pairwise(nums):
            m = max(0, min(k, b - a - 1)) # number of integers to add
            ans += (a + 1 + a + m) * m // 2 # Summation formula
            k -= m
            if k == 0:
                break
        return ans
 

Java:

import java.util.Arrays;
 
class Solution {
    public long minimalKSum(int[] nums, int k) {
        int n = nums.length;
        int[] arr = new int[n + 2]; //add sentinels
        arr[0] = 0;
        arr[n+1] = 2000000000; // large number
        System.arraycopy(nums, 0, arr, 1, n);
        Arrays.sort(arr);
        long ans = 0;
        for (int i = 0; i < n + 1 && k > 0; ++i) {
            int m = Math.max(0, Math.min(k, arr[i + 1] - arr[i] - 1));
            ans += (arr[i] + 1L + arr[i] + m) * m / 2;
            k -= m;
        }
        return ans;
    }
}

C++:

#include <vector>
#include <algorithm>
 
class Solution {
public:
    long long minimalKSum(vector<int>& nums, int k) {
        nums.push_back(0); //add sentinels
        nums.push_back(2000000000); // large number
        sort(nums.begin(), nums.end());
        long long ans = 0;
        for (size_t i = 0; i < nums.size() - 1 && k > 0; ++i) {
            int m = max(0, min(k, nums[i + 1] - nums[i] - 1));
            ans += 1LL * (nums[i] + 1 + nums[i] + m) * m / 2;
            k -= m;
        }
        return ans;
    }
};

(Other languages like Go and TypeScript would follow a similar structure.) Remember to handle potential integer overflows carefully, especially when dealing with large inputs and sums. The use of long long (or equivalent 64-bit integer types) is crucial in C++ and Java to avoid this. In Python, integers handle arbitrary precision, so this is less of a concern.