Problem
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
.
Examples
Example 1:
Input: nums = [3,5,6,7], target = 9
Output: 4
Explanation: 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: 6
Explanation: There are 6 subsequences that satisfy the condition. (nums can have repeated numbers).
[3] , [3] , [3,3], [3,6] , [3,6] , [3,3,6]
Example 3:
Input: nums = [2,3,3,4,6,7], target = 12
Output: 61
Explanation: There are 63 non-empty subsequences, two of them do not satisfy the condition ([6,7], [7]).
Number of valid subsequences (63 - 2 = 61).
Solution
Method 1 - Recursion + Backtracking
graph TD; A("[3, 3, 6, 8], tgt = 10") --> B(3) & C("[]") B --> D("[3,3]") & E("[3]") C --> F("[3]") & G("[]")
Time complexity - O(2^n)
Method 2 - Using Two Sum
- This problem is a variant of the 2Sum Problem.
- In this scenario, the order of numbers in a subsequence is irrelevant; only the maximum and minimum values of the subsequence matter. Therefore, a subsequence from index i to j in the original array is equivalent to an array with the same elements and the same minimum and maximum values. For example, consider
nums = [3, 7, 6, 5]
andtarget = 10
. Here, the subsequence[3, 7, 6]
is equivalent to the subsequence[3, 6, 7]
of the sorted array[3, 5, 6, 7]
. Thus, the result fornums
is the same as the result forsorted(nums)
. - For each index
i
insorted_nums
, identify the maximum indexj
such thatsorted_nums[i] + sorted_nums[j] <= target
andj >= i
. - From
i+1
toj
, each element can either be included or excluded. - Therefore,
res += 2^(j-i)
.
Code
Java
public int numSubseq(int[] nums, int target) {
Arrays.sort(nums); // Sort the array first
int res = 0, n = nums.length, l = 0, r = n - 1;
int mod = (int) 1e9 + 7;
int[] pows = new int[n];
pows[0] = 1;
// Precompute powers of 2 modulo mod
for (int i = 1; i < n; ++i) {
pows[i] = pows[i - 1] * 2 % mod;
}
// Use two pointers to find subsequences
while (l <= r) {
if (nums[l] + nums[r] > target) {
r--;
} else {
res = (res + pows[r - l++]) % mod;
}
}
return res;
}```
#### Complexity
- ⏰ Time complexity: `O(n log n)`, for sorting the array.
- `O(n)` as each element is processed at most twice.
- 🧺 Space complexity: `O(n)`
- **Auxiliary Space**: `O(n)` for storing the precomputed powers of 2 in the array `pows`.