Taro Logo

Number of Subsequences That Satisfy the Given Sum Condition

Medium
Meta logo
Meta
Topics:
ArraysBinary SearchGreedy AlgorithmsDynamic Programming

You are given an array of integers nums and an integer target.

Return the number of non-empty subsequences of nums such that the sum of the minimum and maximum element on it is less or equal to target. Since the answer may be too large, return it modulo 10<sup>9</sup> + 7.

For example:

  1. nums = [3,5,6,7], target = 9. The answer is 4 because the valid subsequences are [3], [3,5], [3,5,6], and [3,6].
  2. nums = [3,3,6,8], target = 10. The answer is 6 because the valid subsequences are [3], [3], [3,3], [3,6], [3,6], and [3,3,6].
  3. nums = [2,3,3,4,6,7], target = 12. The answer is 61.

Explain your solution with time and space complexity.

Solution


Naive Solution

The most straightforward approach is to generate all possible subsequences of the input array nums and then check for each subsequence if the sum of its minimum and maximum elements is less than or equal to target. If the condition is met, we increment a counter.

This involves generating all 2n subsequences, where n is the length of nums. For each subsequence, we need to find the minimum and maximum elements, which takes O(n) time in the worst case. Therefore, the overall time complexity would be O(n * 2n).

This solution will likely result in a Time Limit Exceeded (TLE) error for larger input sizes.

Big(O) Complexity

  • Time Complexity: O(n * 2n)
  • Space Complexity: O(n) (due to recursion stack in subsequence generation)

Optimal Solution

To optimize, we can sort the array nums first. Then, for each element nums[i], we can find the largest index j such that nums[i] + nums[j] <= target. The number of subsequences that can be formed with nums[i] as the minimum element and elements from i+1 to j is 2(j-i). We sum up these values for all possible i to get the final result.

Since the answer can be very large, we must perform the calculations modulo 10^9 + 7.

Algorithm

  1. Sort the input array nums.
  2. Precompute powers of 2 modulo 10^9 + 7.
  3. Iterate through the sorted array from i = 0 to n - 1:
    • For each i, find the largest j such that nums[i] + nums[j] <= target using binary search.
    • If such a j exists, add 2(j-i) to the result (modulo 10^9 + 7).
  4. Return the final result.

Code Example (Python)

def countSubsequences(nums, target):
    nums.sort()
    n = len(nums)
    MOD = 10**9 + 7

    # Precompute powers of 2
    power = [1] * (n + 1)
    for i in range(1, n + 1):
        power[i] = (power[i - 1] * 2) % MOD

    count = 0
    for i in range(n):
        left = i
        right = n - 1
        j = -1
        while left <= right:
            mid = (left + right) // 2
            if nums[i] + nums[mid] <= target:
                j = mid
                left = mid + 1
            else:
                right = mid - 1

        if j != -1:
            count = (count + power[j - i]) % MOD

    return count

Edge Cases

  • Empty array: The problem states that the subsequences must be non-empty, so an empty input array is not a valid case.
  • Single element array: If the array has only one element, we simply check if 2 * nums[0] <= target.
  • Duplicate elements: The solution handles duplicate elements correctly because we are considering all possible subsequences.
  • target smaller than the smallest element: If the target is smaller than twice the smallest element, there are no valid subsequences.
  • Large input size with a large number of valid subsequences: Modulo operation is crucial to prevent overflow.

Big(O) Complexity

  • Time Complexity: O(n log n) due to sorting, and O(n log n) for binary search within the loop which simplifies to O(n log n)
  • Space Complexity: O(n) for storing the powers of 2 and potentially for sorting, depending on the sorting algorithm used. It may be O(1) if an in-place sorting algorithm is used.