709911. Subset sums between the given range
Subset Sums between the Given Range
Summary
Given a set of integers and two integers low and high, find all subsets of the given set whose sum falls within the range [low, high].
This problem involves dynamic programming and subset generation.
Detailed Explanation
We will solve this problem using dynamic programming. The idea is to build up a 2D table where each cell (i, j) represents whether there exists a subset of the first i numbers that sums up to j. We then iterate over all possible subsets and check if their sum falls within the given range.
Here's a step-by-step breakdown:
- Initialize a 2D table
dpwith dimensions(n + 1, high - low + 1), wherenis the size of the input set. - Iterate over all numbers in the input set. For each number
x, iterate fromhigh - lowdown tolow. For eachjin this range:- If
xis greater thanj, there's no way a subset that includesxcan sum up toj. So, setdp[i][j] = dp[i-1][j]. - Otherwise, consider two cases: including
xin the subset and not including it. If either case sums up toj, markdp[i][j] = true.
- If
- Initialize an empty list to store the result.
- Iterate over all possible subsets of the input set (this can be done using a recursive function that generates all subsets). For each subset:
- Calculate its sum and check if it falls within the given range.
- If it does, add the subset to the result list.
Time complexity: O(n * high - low), where n is the size of the input set. This is because we iterate over all numbers in the input set once and then over the entire range [low, high].
Space complexity: O(n + high - low), as we need to store the dynamic programming table.
Optimized Solutions
Java
public class Main {
public static List<List<Integer>> subsetSums(int[] nums, int low, int high) {
List<List<Integer>> result = new ArrayList<>();
int n = nums.length;
boolean[][] dp = new boolean[n + 1][high - low + 1];
// Initialize dp table
for (int i = 0; i <= n; i++) {
dp[i][0] = true;
}
// Fill up the dp table
for (int i = 1; i <= n; i++) {
for (int j = high - low; j >= 0; j--) {
if (nums[i-1] > j) {
dp[i][j] = dp[i-1][j];
} else {
dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]];
}
}
}
// Generate all subsets that sum up to a value in the range
for (int i = 0; i <= n; i++) {
for (int j = high - low; j >= 0; j--) {
if (dp[i][j]) {
List<Integer> subset = new ArrayList<>();
generateSubset(nums, i, j, subset);
result.add(subset);
}
}
}
return result;
}
private static void generateSubset(int[] nums, int n, int sum, List<Integer> subset) {
if (n == 0) {
return;
}
for (int i = 0; i <= n; i++) {
if (i > 0) {
generateSubset(Arrays.copyOfRange(nums, i, nums.length), n-i, sum-nums[i-1], subset);
subset.add(nums[i-1]);
} else {
generateSubset(Arrays.copyOfRange(nums, i, nums.length), n, sum-nums[0], subset);
subset.add(0);
}
}
}
}