Problem

Given an integer array nums of length n and an integer k, return thekth smallest subarray sum.

A subarray is defined as a non-empty contiguous sequence of elements in an array. A subarray sum is the sum of all elements in the subarray.

Examples

Example 1:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Input: nums = [2,1,3], k = 4
Output: 3
Explanation: The subarrays of [2,1,3] are:
- [2] with sum 2
- [1] with sum 1
- [3] with sum 3
- [2,1] with sum 3
- [1,3] with sum 4
- [2,1,3] with sum 6 
Ordering the sums from smallest to largest gives 1, 2, 3, _3_ , 4, 6. The 4th smallest is 3.

Example 2:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Input: nums = [3,3,5,5], k = 7
Output: 10
Explanation: The subarrays of [3,3,5,5] are:
- [3] with sum 3
- [3] with sum 3
- [5] with sum 5
- [5] with sum 5
- [3,3] with sum 6
- [3,5] with sum 8
- [5,5] with sum 10
- [3,3,5], with sum 11
- [3,5,5] with sum 13
- [3,3,5,5] with sum 16
Ordering the sums from smallest to largest gives 3, 3, 5, 5, 6, 8, _10_ , 11, 13, 16. The 7th smallest is 10.

Constraints:

  • n == nums.length
  • 1 <= n <= 2 * 10^4
  • 1 <= nums[i] <= 5 * 10^4
  • 1 <= k <= n * (n + 1) / 2

Solution

Method 1 – Binary Search with Sliding Window

Intuition

The k-th smallest subarray sum can be found by binary searching the possible sum values and, for each candidate sum, counting how many subarrays have sum ≤ that value. The counting can be done efficiently using a sliding window since all elements are positive.

Approach

  1. Set left = min(nums), right = sum(nums).
  2. While left < right:
    • Compute mid = (left + right) // 2.
    • Count the number of subarrays with sum ≤ mid using a sliding window.
    • If the count ≥ k, set right = mid; else, set left = mid + 1.
  3. Return left as the answer.

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Solution {
public:
    int kthSmallestSubarraySum(vector<int>& nums, int k) {
        int l = *min_element(nums.begin(), nums.end()), r = accumulate(nums.begin(), nums.end(), 0);
        while (l < r) {
            int m = (l + r) / 2, cnt = 0, sum = 0, j = 0;
            for (int i = 0; i < nums.size(); ++i) {
                sum += nums[i];
                while (sum > m) sum -= nums[j++];
                cnt += i - j + 1;
            }
            if (cnt >= k) r = m;
            else l = m + 1;
        }
        return l;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func kthSmallestSubarraySum(nums []int, k int) int {
    l, r := nums[0], 0
    for _, v := range nums {
        if v < l { l = v }
        r += v
    }
    for l < r {
        m := (l + r) / 2
        cnt, sum, j := 0, 0, 0
        for i := 0; i < len(nums); i++ {
            sum += nums[i]
            for sum > m {
                sum -= nums[j]
                j++
            }
            cnt += i - j + 1
        }
        if cnt >= k {
            r = m
        } else {
            l = m + 1
        }
    }
    return l
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Solution {
    public int kthSmallestSubarraySum(int[] nums, int k) {
        int l = Arrays.stream(nums).min().getAsInt(), r = Arrays.stream(nums).sum();
        while (l < r) {
            int m = (l + r) / 2, cnt = 0, sum = 0, j = 0;
            for (int i = 0; i < nums.length; ++i) {
                sum += nums[i];
                while (sum > m) sum -= nums[j++];
                cnt += i - j + 1;
            }
            if (cnt >= k) r = m;
            else l = m + 1;
        }
        return l;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
    fun kthSmallestSubarraySum(nums: IntArray, k: Int): Int {
        var l = nums.minOrNull()!!
        var r = nums.sum()
        while (l < r) {
            val m = (l + r) / 2
            var cnt = 0
            var sum = 0
            var j = 0
            for (i in nums.indices) {
                sum += nums[i]
                while (sum > m) {
                    sum -= nums[j]
                    j++
                }
                cnt += i - j + 1
            }
            if (cnt >= k) r = m else l = m + 1
        }
        return l
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Solution:
    def kthSmallestSubarraySum(self, nums: list[int], k: int) -> int:
        l, r = min(nums), sum(nums)
        while l < r:
            m = (l + r) // 2
            cnt = 0
            s = j = 0
            for i, v in enumerate(nums):
                s += v
                while s > m:
                    s -= nums[j]
                    j += 1
                cnt += i - j + 1
            if cnt >= k:
                r = m
            else:
                l = m + 1
        return l
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
impl Solution {
    pub fn kth_smallest_subarray_sum(nums: Vec<i32>, k: i32) -> i32 {
        let (mut l, mut r) = (*nums.iter().min().unwrap(), nums.iter().sum());
        while l < r {
            let m = (l + r) / 2;
            let (mut cnt, mut sum, mut j) = (0, 0, 0);
            for i in 0..nums.len() {
                sum += nums[i];
                while sum > m { sum -= nums[j]; j += 1; }
                cnt += i as i32 - j as i32 + 1;
            }
            if cnt >= k { r = m; } else { l = m + 1; }
        }
        l
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Solution {
    kthSmallestSubarraySum(nums: number[], k: number): number {
        let l = Math.min(...nums), r = nums.reduce((a, b) => a + b, 0);
        while (l < r) {
            const m = Math.floor((l + r) / 2);
            let cnt = 0, sum = 0, j = 0;
            for (let i = 0; i < nums.length; ++i) {
                sum += nums[i];
                while (sum > m) sum -= nums[j++];
                cnt += i - j + 1;
            }
            if (cnt >= k) r = m;
            else l = m + 1;
        }
        return l;
    }
}

Complexity

  • ⏰ Time complexity: O(n log S), where n is the length of nums and S is the sum of nums. Each binary search step counts subarrays in O(n).
  • 🧺 Space complexity: O(1), only a few variables are used.