LeetCode90 子集 II 排序+子问题求解
以nums={1,2,2,3}
为例,将问题划分为求nums={1}
, nums={2,2}
, nums={3}
三个子问题,然后将子结果合并。这里子问题是求非空子集
求子问题
nums={1}
的非空子集{{1}}
nums={2,2}
的非空子集{{2},{2,2}}
nums={3}
的非空子集{{3}}
合并子结果
-
{{1}}
与{{2},{2,2}}
的组合:- 只使用
nums={1}
的结果,即{{1}}
- 只使用
nums={2,2}
的结果,即{{2},{22}}
- 使用
nums={1}
与nums={2}
组合的结果,{{1,2},{1,2,2}}
- 综上三种情况:组合的结果为
{{1},{2},{22},{1,2},{1,2,2}}
,然后再将结果与nums={3}
的结果组合
// 组合代码 /** * 将两个子结果组合 * @param listA * @param listB * @return */ public static List<List<Integer>> group(List<List<Integer>> listA, List<List<Integer>> listB) { List<List<Integer>> res = new ArrayList<>(); // 只使用子结果A res.addAll(listA); // 只使用子结果B res.addAll(listB); // 即使用子结果A 也使用 子结果B for (List<Integer> itemA : listA) { for (List<Integer> itemB : listB) { List<Integer> sub = new ArrayList<>(itemA); sub.addAll(itemB); res.add(sub); } } return res; }
- 只使用
划分子问题
- 排序
- 将连续相等的数字作为一个子问题求解
代码
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
// 排序, 用于避免重复
Arrays.sort(nums);
// 当前下标
int index = 0;
// nums[index] = nums[j]; j in [index+1, index+continued)
int continued = 1;
while (index < nums.length) {
// 这里需要重置 continued
continued = 1;
while (index + continued < nums.length && nums[index] == nums[index + continued]) {
continued++;
}
List<List<Integer>> sub = subSolution(nums[index], continued);
res = group(res, sub);
index+=continued;
}
// 添加空集
List<Integer> empty = new ArrayList<>();
res.add(empty);
return res;
}
/**
* 求子结果
* num: 数字
* n : 重复次数
*/
public List<List<Integer>> subSolution(int num, int n){
List<List<Integer>> res = new ArrayList<>();
res.add(new ArrayList<>(Arrays.asList(num)));
for (int i = 1; i < n; i++) {
res.add(new ArrayList<>(res.get(i - 1)));
res.get(i).add(num);
}
return res;
}
/**
* 将两个子结果组合
* @param listA
* @param listB
* @return
*/
public static List<List<Integer>> group(List<List<Integer>> listA, List<List<Integer>> listB) {
List<List<Integer>> res = new ArrayList<>();
// 只使用子结果A
res.addAll(listA);
// 只使用子结果B
res.addAll(listB);
// 即使用子结果A 也使用 子结果B
for (List<Integer> itemA : listA) {
for (List<Integer> itemB : listB) {
List<Integer> sub = new ArrayList<>(itemA);
sub.addAll(itemB);
res.add(sub);
}
}
return res;
}
}
唉,又臭又长,距离一行代码还很遥远