1. 子集 II
90. 子集 IIhttps://leetcode.cn/problems/subsets-ii/
给你一个整数数组 nums
,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例 1:
输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
解题思路
相较于78. 子集来说,nums有重复的元素,所以难点提升在于,在一个子集内部可以取重复元素,但是在子集外部不能取。使用一个Boolean数组记录。
代码
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
boolean[] mark;
public List<List<Integer>> subsetsWithDup(int[] nums) {
mark = new boolean[nums.length];
Arrays.fill(mark, false);
Arrays.sort(nums);
backTrack(nums, 0);
return res;
}
private void backTrack(int[] nums, int index) {
res.add(new ArrayList(path));
if (index == nums.length)
return;
for (int i = index; i < nums.length; i++) {
if (i > 0 && nums[i] == nums[i - 1] && !mark[i - 1]) {
continue;
}
path.add(nums[i]);
mark[i] = true;
backTrack(nums, i + 1);
path.removeLast();
mark[i] = false;
}
}
}
2. 非递减子序列
491. 非递减子序列https://leetcode.cn/problems/non-decreasing-subsequences/
给你一个整数数组 nums
,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。
数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。
示例 1:
输入:nums = [4,6,7,7]
输出:[[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]
示例 2:
输入:nums = [4,4,3,2,1]
输出:[[4,4]]
解题思路
非递减,也就是说会有重复元素,并且序列长度至少为2,所以回溯中有不同的地方,首先是重复元素,重复元素不是挨着的,不能使用一个数组进行标记了,需要使用一个set记录,通一层的取值中,取过的就应该跳过。其次是加一个参数来判定当前长度是否大于1。再然后是需要判定即将取的值和上一个值大小的比较,不符合就跳过。
代码
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
backTrack(nums, 0, 0);
return res;
}
private void backTrack(int[] nums, int index, int count) {
if (count > 1)
res.add(new ArrayList(path));
if (index == nums.length)
return;
Set<Integer> set = new HashSet<>();
for (int i = index; i < nums.length; i++) {
if (count > 0 && nums[i] < path.getLast())
continue;
if (set.contains(nums[i])) {
continue;
}
path.add(nums[i]);
set.add(nums[i]);
backTrack(nums, i + 1, count + 1);
path.removeLast();
}
}
}