一个人的朝圣 — LeetCode打卡第29天
知识总结
依旧运用模板, 但是具体问题需要具体的分析, 包括重复的讨论。
Leetcode 491. 递增子序列
题目说明
给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。
数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。
代码说明
特殊情况: 【1,2,3,4,1,1,1】 这里不能排序后和前面的的比较, 所以引用了hashset。
class Solution {
public List<List<Integer>> res = new ArrayList<>();
public LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
backtrack(nums, 0);
return res;
}
private void backtrack(int[] nums, int startIndex){
if(path.size() >= 2) res.add(new ArrayList<>(path));
if(startIndex == nums.length) return;
Set<Integer> level = new HashSet<>();
for(int i = startIndex; i < nums.length; i++){
if(level.contains(nums[i])) continue;
level.add(nums[i]);
if(path.size() == 0 || path.getLast() <= nums[i]){
path.add(nums[i]);
backtrack(nums, i+1);
path.removeLast();
}
}
}
}
也有一种高级的写法, 难理解一些。
做选择, 要么选择这个,要么不选。 如果前面选过了, 且当前的不一样, 我就可以选择跳过当前的元素。
class Solution {
List<Integer> temp = new ArrayList<Integer>();
List<List<Integer>> ans = new ArrayList<List<Integer>>();
public List<List<Integer>> findSubsequences(int[] nums) {
dfs(0, Integer.MIN_VALUE, nums);
return ans;
}
public void dfs(int cur, int last, int[] nums) {
if (cur == nums.length) {
if (temp.size() >= 2) {
ans.add(new ArrayList<Integer>(temp));
}
return;
}
// 选择该当前的, 更新last
if (nums[cur] >= last) {
temp.add(nums[cur]);
dfs(cur + 1, nums[cur], nums);
temp.remove(temp.size() - 1);
}
// 不选择当前的, 前提时当前的 != 上一个
if (nums[cur] != last) {
dfs(cur + 1, last, nums);
}
}
}
Leetcode 46. 全排列
题目说明
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
代码说明
- 用used数组表示当前是否用过这个元素
- for循环从0开始而不是startIndex
class Solution {
public List<List<Integer>> res = new ArrayList<>();
public LinkedList<Integer> path = new LinkedList<>();
public boolean[] used;
public List<List<Integer>> permute(int[] nums) {
used = new boolean[nums.length];
backtrack(nums);
return res;
}
public void backtrack(int[] nums){
if(path.size() == nums.length){
res.add(new ArrayList<>(path));
return;
}
for(int i = 0; i < nums.length; i++){
if(used[i]){
continue;
}
used[i] = true;
path.add(nums[i]);
backtrack(nums);
path.removeLast();
used[i] = false;
}
}
}
Leetcode 47. 全排列 II
题目说明
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
代码说明
class Solution {
public List<List<Integer>> res = new ArrayList<>();
public LinkedList<Integer> path = new LinkedList<>();
public boolean[] used;
public List<List<Integer>> permuteUnique(int[] nums) {
used = new boolean[nums.length];
backtrack(nums);
return res;
}
public void backtrack(int[] nums){
if(path.size() == nums.length){
res.add(new ArrayList<>(path));
return;
}
HashSet<Integer> level = new HashSet<>();
for(int i = 0; i < nums.length; i++){
if(used[i]|| level.contains(nums[i])){
continue;
}
used[i] = true;
level.add(nums[i]);
path.add(nums[i]);
backtrack(nums);
path.removeLast();
used[i] = false;
}
}
}