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^9) + 7.
Example 1:
Input: nums = [3,5,6,7], target = 9
Output: 4Explanation: There are 4 subsequences that satisfy the condition.
[3] -> Min value + max value <= target (3 + 3 <= 9)
[3,5] -> (3 + 5 <= 9)
[3,5,6] -> (3 + 6 <= 9)
[3,6] -> (3 + 6 <= 9)
Example 2:
Input: nums = [3,3,6,8], target = 10
Output: 6Explanation: There are 6 subsequences that satisfy the condition. (nums can have repeated numbers).
[3] , [3] , [3,3], [3,6] , [3,6] , [3,3,6]
Constraints:
1 <= nums.length <= 100,0001 <= nums[i], target <= 1,000,000Before attempting this problem, you should be comfortable with:
We generate all possible subsequences using recursion, tracking the minimum and maximum values chosen so far. If a non-empty subsequence has min + max <= target, we count it. This explores the full power set of the array.
max, and running min.min and max.min + max <= target.10^9 + 7.class Solution:
def numSubseq(self, nums: List[int], target: int) -> int:
MOD = 1000000007
def dfs(maxi, mini, i):
if i == len(nums):
if mini != float("inf") and (maxi + mini) <= target:
return 1
return 0
skip = dfs(maxi, mini, i + 1)
include = dfs(max(maxi, nums[i]), min(mini, nums[i]), i + 1)
return (skip + include) % MOD
return dfs(float("-inf"), float("inf"), 0)After sorting, for each element as the minimum, we use binary search to find the rightmost element that can serve as the maximum (where min + max <= target). All elements between these two positions can freely be included or excluded, giving 2^(count) valid subsequences with this minimum.
i where nums[i] * 2 <= target (it can be both min and max):r where nums[i] + nums[r] <= target.i and r can each be included or not, giving 2^(r-i) subsequences.10^9 + 7.class Solution:
def numSubseq(self, nums: List[int], target: int) -> int:
nums.sort()
MOD = 1000000007
res = 0
for i in range(len(nums)):
if nums[i] * 2 > target:
break
l, r = i, len(nums) - 1
while l <= r:
mid = (l + r) // 2
if nums[i] + nums[mid] <= target:
l = mid + 1
else:
r = mid - 1
count = pow(2, r - i, MOD)
res = (res + count) % MOD
return resAfter sorting, we use two pointers. The left pointer represents the minimum element we must include. The right pointer starts at the end and shrinks inward until the sum constraint is satisfied. Since the array is sorted, once the right pointer moves left, it never needs to go back.
0, right pointer at the last index.nums[left] + nums[right] <= target.(left <= right), add 2^(right - left) subsequences.10^9 + 7.class Solution:
def numSubseq(self, nums: List[int], target: int) -> int:
nums.sort()
res = 0
mod = 10**9 + 7
r = len(nums) - 1
for i, left in enumerate(nums):
while i <= r and left + nums[r] > target:
r -= 1
if i <= r:
res += pow(2, r - i, mod)
res %= mod
return resWe precompute all powers of 2 up to n to avoid repeated exponentiation. The two pointer logic moves inward from both ends: if the current pair satisfies the constraint, count the subsequences and advance the left pointer; otherwise, shrink the right pointer.
power[i] = 2^i mod (10^9 + 7) for i from 0 to n-1.left <= right:nums[left] + nums[right] <= target, add power[right - left] to res and increment left.right.class Solution:
def numSubseq(self, nums: List[int], target: int) -> int:
nums.sort()
MOD = 1000000007
res = 0
l, r = 0, len(nums) - 1
power = [1] * len(nums)
for i in range(1, len(nums)):
power[i] = (power[i - 1] * 2) % MOD
while l <= r:
if nums[l] + nums[r] <= target:
res = (res + power[r - l]) % MOD
l += 1
else:
r -= 1
return resThe two-pointer and binary search approaches require a sorted array. Since we only care about the minimum and maximum values in each subsequence (not their order), sorting is valid and necessary. Forgetting to sort leads to incorrect results because the two-pointer logic assumes sorted order.
Computing 2^(r-l) can produce astronomically large numbers. Using naive exponentiation without modular arithmetic causes overflow. You must use modular exponentiation or precompute powers with modulo applied at each step to avoid this issue.
For a valid range from index l to r where nums[l] is the minimum, there are 2^(r-l) valid subsequences, not 2^(r-l+1). This is because we must include nums[l] (it's the minimum), but any subset of the remaining r-l elements can be included. Off-by-one errors in this exponent are common.