title: Append K Integers With Minimal Sum slug: append-k-integers-with-minimal-sum difficulty: medium leetcode_id: 2195 leetcode_url: https://leetcode.com/problems/append-k-integers-with-minimal-sum/ categories: - arrays - math - sorting patterns: - greedy description: | 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`. constraints: | - `1 <= nums.length <= 10^5` - `1 <= nums[i] <= 10^9` - `1 <= k <= 10^8` examples: - 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 sum of the two integers appended is 2 + 3 = 5." - 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 sum is 1 + 2 + 3 + 4 + 7 + 8 = 25." explanation: intuition: | To minimise the sum, we want to pick the **smallest possible positive integers** that aren't already in `nums`. Imagine counting from 1 upward: 1, 2, 3, 4, ... and skipping any number that already exists in the array. The key insight is that we don't need to iterate through each number one by one. Instead, we can use the **arithmetic series formula** to calculate sums of consecutive integers in bulk: the sum of integers from `1` to `n` is `n * (n + 1) / 2`. Think of it like filling gaps: if `nums` contains some numbers that "block" certain positions, we need to count how many integers we can pick before hitting a blocker, calculate that sum efficiently, then jump past the blocker and continue. By sorting `nums` and processing gaps between consecutive elements, we can quickly determine how many "free" integers exist in each range and compute their sum using the formula. approach: | We solve this using a **Greedy Gap-Filling Approach**: **Step 1: Sort and deduplicate the array** - Sort `nums` to process elements in order - Remove duplicates since they don't affect which integers are "taken"   **Step 2: Initialise tracking variables** - `result`: Accumulates the sum of chosen integers (starts at `0`) - `prev`: Tracks the last integer we've considered (starts at `0`, meaning we begin from `1`)   **Step 3: Process each number in the sorted array** - For each number `num` in the sorted array, calculate the gap: how many integers exist between `prev + 1` and `num - 1` inclusive - The count of available integers in this gap is `num - prev - 1` - If the gap has more integers than we still need (`k`), we only take `k` of them - Use the arithmetic series formula to add the sum of the integers we take: sum from `prev + 1` to `prev + take` is `take * (2 * prev + take + 1) / 2` - Subtract the taken count from `k` and update `prev = num` - If `k` reaches `0`, we're done   **Step 4: Handle remaining integers after the array** - If `k > 0` after processing all elements, we need `k` more integers starting from `prev + 1` - Add the sum of integers from `prev + 1` to `prev + k` using the arithmetic series formula   **Step 5: Return the result** - Return the accumulated `result` sum common_pitfalls: - title: Iterating One-by-One description: | With `k` up to `10^8`, iterating through each integer individually and checking membership would be far too slow. For example, if `nums = [10^9]` and `k = 10^8`, you'd need to check and sum 100 million integers one at a time. This results in **O(k)** operations which causes TLE. Instead, use the arithmetic series formula `n * (n + 1) / 2` to calculate sums of ranges in **O(1)** time. wrong_approach: "Loop through integers 1, 2, 3, ... checking each" correct_approach: "Calculate range sums using arithmetic series formula" - title: Not Handling Duplicates description: | The input array can contain duplicate values (e.g., `[1,4,25,10,25]`). If you don't deduplicate, you might incorrectly count the same "blocked" position multiple times. For instance, with `nums = [2, 2, 2]`, the integer `2` only blocks one position, not three. Deduplicating ensures each blocked position is counted exactly once. wrong_approach: "Process array with duplicates" correct_approach: "Convert to set or deduplicate after sorting" - title: Integer Overflow description: | The sum of `k` integers (where `k` can be `10^8`) starting from 1 is approximately `k * k / 2`, which can exceed `10^16`. In languages with fixed-size integers, this can cause overflow. Python handles arbitrary precision integers automatically, but in other languages you'd need to use 64-bit integers (`long long` in C++, `Long` in Java). wrong_approach: "Use 32-bit integers for sum calculation" correct_approach: "Use 64-bit integers or language with arbitrary precision" - title: Off-by-One Errors in Gap Calculation description: | When calculating the number of integers between `prev` and `num`, it's easy to make off-by-one mistakes. The count of integers from `a` to `b` inclusive is `b - a + 1`. The gap between `prev` (exclusive) and `num` (exclusive) contains `num - prev - 1` integers. Example: between `prev = 2` and `num = 5`, the available integers are `3, 4` — that's `5 - 2 - 1 = 2` integers. wrong_approach: "Miscounting gap size" correct_approach: "Gap from prev to num (exclusive both) is num - prev - 1" key_takeaways: - "**Arithmetic series formula**: Sum from 1 to n is `n * (n + 1) / 2`. This transforms O(n) iteration into O(1) calculation" - "**Gap-filling strategy**: When filling positions with constraints, sort the constraints and process gaps between them" - "**Greedy correctness**: Taking the smallest available integers first always yields the minimum sum — no need to consider alternatives" - "**Handle large ranges**: When k or values can be very large, look for mathematical formulas to avoid iteration" time_complexity: "O(n log n). Sorting dominates the complexity; processing the sorted array is O(n)." space_complexity: "O(n). We store the deduplicated sorted array. Can be O(1) extra space if we sort in-place and handle duplicates during iteration." solutions: - approach_name: Greedy with Arithmetic Series is_optimal: true code: | def min_sum(nums: list[int], k: int) -> int: # Sort and deduplicate to process gaps in order nums = sorted(set(nums)) result = 0 prev = 0 # Last integer we've accounted for (start before 1) for num in nums: # How many integers are available between prev and num? gap = num - prev - 1 if gap > 0: # Take at most k integers from this gap take = min(gap, k) # Sum of integers from (prev + 1) to (prev + take) # Using formula: sum = take * (first + last) / 2 first = prev + 1 last = prev + take result += take * (first + last) // 2 k -= take if k == 0: return result prev = num # Still need more integers after the last element in nums if k > 0: first = prev + 1 last = prev + k result += k * (first + last) // 2 return result explanation: | **Time Complexity:** O(n log n) — Sorting the array dominates; iteration is O(n). **Space Complexity:** O(n) — Creating a sorted set of unique elements. We process gaps between consecutive elements in the sorted array, using the arithmetic series formula to efficiently sum ranges of consecutive integers. This avoids iterating through potentially billions of integers. - approach_name: Brute Force (TLE) is_optimal: false code: | def min_sum(nums: list[int], k: int) -> int: # Convert to set for O(1) lookup num_set = set(nums) result = 0 current = 1 # Find k integers not in nums while k > 0: if current not in num_set: result += current k -= 1 current += 1 return result explanation: | **Time Complexity:** O(k + n) — We iterate up to k + max(nums) times in the worst case. **Space Complexity:** O(n) — Storing nums in a set. This straightforward approach iterates through positive integers one by one, adding those not in nums. While correct, it's far too slow when k is large (up to 10^8). Included to illustrate why the arithmetic series approach is necessary.