1. 自增子序列
1.1 链接
https://leetcode.cn/problems/non-decreasing-subsequences/
1.2 关键知识点
-//本题求自增子序列,是不能对原数组进行排序的,排完序的数组都是自增子序列了。所以不能使用之前的去重逻辑!
1.3 自己遇到的细节问题
- LinkedList长度是size
- map.getOrDefault(nums[i], 0)获取值的使用
1.4 题解
class Solution {
//根本还是求子集
//本题求自增子序列,是不能对原数组进行排序的,排完序的数组都是自增子序列了。所以不能使用之前的去重逻辑!
List<List<Integer>> rs = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
backTracking(nums, 0);
return rs;
}
public void backTracking(int[] nums, int startIdx){
if(path.size() >= 2){
rs.add(new ArrayList<>(path));
}
//每一层判断
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = startIdx; i < nums.length; i ++){
//父子的判断逻辑 以及层间的
if((!path.isEmpty() && path.getLast() > nums[i]) || map.getOrDefault(nums[i], 0) > 0){
continue;
}else{
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
path.add(nums[i]);
backTracking(nums, i + 1);
path.removeLast();
}
}
}
}
2.全排列
为什么排列问题不用 startIndex?可以理解成一个单向一个双向。startindex的存在就是构造一个单向。
2.1 链接
https://leetcode.cn/problems/permutations/
2.2 关键知识点
- 不重复选取数字的设置:由于排列问题和组合问题不同,不需要startindex来每次获取序列的后部分(换句话说是通过i+1实现的),而是i=0,开始,因此需要一个used数组来判断是否挑选到了上层数字;
2.3 自己遇到的细节问题
- 注意用path比
-注意一定要转为正确的ArrayList,不然传进去是空
2.4 题解
class Solution {
List<List<Integer>> rs = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
boolean[] used;//默认值为false
public List<List<Integer>> permute(int[] nums) {
used = new boolean[nums.length];//used初始化
backTracking(nums);
return rs;
}
public void backTracking(int[] nums){
if(nums.length == path.size()){//注意用path比
rs.add(new ArrayList<>(path));//注意一定要转为正确的ArrayList,不然传进去是空
}
for(int i = 0; i < nums.length; i ++){
if(!used[i]){//为了跳过当前数字
used[i] = true;
path.add(nums[i]);
backTracking(nums);
used[i] = false;
path.removeLast();
}//这样写没有continue也行
}
}
}
3.全排列Ⅱ
3.1 链接
https://leetcode.cn/problems/permutations-ii/
3.2 关键知识点
如果排列问题去重(i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false),和组合问题去重相比
- 类似但不同:树层的进入大于1:不再通过startindex判断一个树层的进入,而是i>0就代表树层的进入;
- 不同:树层已经被使用(组合问题中没有的条件,因为每次输入的i+1就跳过了用过的):并且跳过使用过的同一树层(因为可能正在作为上树层被跳过,而在本树层虽然与前一个相同但未被使用)
- 相同:需要排序,类似于组合问题的相等判断
3.3 自己遇到的细节问题
- 树层去重和树枝去重的理解
- 又忘记排序了。。
3.4 题解
class Solution {
List<List<Integer>> rs = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
boolean[] used;
public List<List<Integer>> permuteUnique(int[] nums) {
used = new boolean[nums.length];
Arrays.sort(nums);//一定要记得排序。。
backTracking(nums);
return rs;
}
public void backTracking(int[] nums){
if(path.size() == nums.length){
rs.add(new ArrayList<>(path));
return;
}
for(int i = 0; i < nums.length; i ++){
if(i > 0 && used[i - 1] == false && nums[i] == nums[i - 1]){//树层没用+连续相等(基于排序)
continue;//去重
}else{
if(!used[i]){
used[i] = true;
path.add(nums[i]);
backTracking(nums);
used[i] = false;
path.removeLast();
}
}
}
}
}