{x}
blog image

Find the K-Sum of an Array

You are given an integer array nums and a positive integer k. You can choose any subsequence of the array and sum all of its elements together.

We define the K-Sum of the array as the kth largest subsequence sum that can be obtained (not necessarily distinct).

Return the K-Sum of the array.

A subsequence is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.

Note that the empty subsequence is considered to have a sum of 0.

 

Example 1:

Input: nums = [2,4,-2], k = 5
Output: 2
Explanation: All the possible subsequence sums that we can obtain are the following sorted in decreasing order:
- 6, 4, 4, 2, 2, 0, 0, -2.
The 5-Sum of the array is 2.

Example 2:

Input: nums = [1,-2,3,4,-10,12], k = 16
Output: 10
Explanation: The 16-Sum of the array is 10.

 

Constraints:

  • n == nums.length
  • 1 <= n <= 105
  • -109 <= nums[i] <= 109
  • 1 <= k <= min(2000, 2n)

Solution Explanation: Find the K-Sum of an Array

This problem asks to find the k-th largest subsequence sum of a given integer array. A brute-force approach would generate all possible subsequence sums, sort them, and return the k-th largest. However, this is computationally expensive, with a time complexity exponential to the array size. The optimal solution leverages a min-heap (priority queue) to efficiently find the k-th largest sum.

Approach:

  1. Handle Negative Numbers: The algorithm simplifies by converting all negative numbers to their positive counterparts. The maximum subsequence sum (the sum of all positive numbers) is calculated and stored in mx. This step reduces the problem to finding the k-th smallest subsequence sum using the transformed positive numbers, because any subsequence sum from the original array is a difference between mx and a specific subsequence sum of the transformed positive numbers.

  2. Sorting: The transformed positive numbers are sorted in ascending order. This enables an efficient way to generate subsequence sums in an organized manner.

  3. Min-Heap: A min-heap is used to store potential subsequence sums. Each element in the heap is a pair (sum, index), where sum is the current subsequence sum and index is the index of the next number to consider for extending the subsequence.

  4. Iterative Refinement: The algorithm iteratively refines the heap. In each iteration, the smallest sum (top of the heap) is extracted. Two new sums are then generated and pushed onto the heap:

    • One by adding the next number from the sorted array to the extracted sum.
    • The other by skipping the next number (essentially continuing the same subsequence with the next number not added).
  5. K-th Smallest: This process continues until k-1 elements have been extracted from the heap. The remaining smallest element in the heap represents the k-th smallest sum using the transformed array. The k-th largest sum in the original array is calculated as mx - kth_smallest_sum.

Time and Space Complexity Analysis:

  • Time Complexity: The dominant operations are sorting the array (O(n log n)) and heap operations (O(k log k)). The overall time complexity is O(n log n + k log k).

  • Space Complexity: The space complexity is determined mainly by the size of the heap and the sorted array, which are both proportional to the array size. Therefore, the space complexity is O(n).

Code Implementation (Python):

import heapq
 
class Solution:
    def kSum(self, nums: List[int], k: int) -> int:
        mx = 0
        for i, x in enumerate(nums):
            if x > 0:
                mx += x
            else:
                nums[i] = -x  # Convert negative numbers to positive
        nums.sort()
        h = [(0, 0)]  # Initialize min-heap with (sum, index) = (0, 0)
        for _ in range(k - 1):
            s, i = heapq.heappop(h)
            if i < len(nums):
                heapq.heappush(h, (s + nums[i], i + 1))  # Add next number
                if i:
                    heapq.heappush(h, (s + nums[i] - nums[i - 1], i + 1)) # Skip next number
        return mx - h[0][0] # kth largest sum = mx - kth smallest sum
 

The Java, C++, and Go implementations follow a similar structure, adapting the data structures and syntax of their respective languages. The core algorithmic logic remains the same across all implementations.