Day25
491.递增子序列
力扣题目链接
给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。
示例:
输入: [4, 6, 7, 7]
输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]
思路
有难度的一道题
需要注意两个点,首先是去重不能简单比较这个元素和上一个是否相等,需要看这一层是否使用过这个元素,如果使用过就直接continue,没有使用过就加入到map中
之后是要比较每个元素和path中加入的上一个元素,如果小就不递增,注意不是比较数组中上一个位置的元素
代码
class Solution {
ArrayList<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
backtracking(nums, 0);
return res;
}
public void backtracking(int[] nums, int startIndex) {
if (path.size() >= 2) {
res.add(new ArrayList<>(path));//至少由两个元素才加入res中
}
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = startIndex; i < nums.length; i++) {
if (!path.isEmpty() && nums[i] < path.getLast()) {//不递增
continue;
}
if (map.getOrDefault(nums[i], 0) >= 1) {//这层中已有重复元素
continue;
}
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);//放入map中
path.addLast(nums[i]);
backtracking(nums, i + 1);
path.removeLast();
}
}
}
46.全排列
力扣题目链接
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
思路
排列问题和组合问题不同,排列问题是有顺序的,因此没法设置startIndex,选了这个元素可能还要回头重新考虑顺序
其实简单了很多,我们每次加入元素的时候看看有没有选过,没选过就加入即可,每次遍历都从第一个元素开始而不是0开始即可
代码
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> permute(int[] nums) {
if (nums == null || nums.length == 0) return res;
backtracking(nums);
return res;
}
private void backtracking(int[] nums){
if (path.size() == nums.length){
res.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < nums.length; i++){//每次都从0开始
if (path.contains(nums[i])) continue;//如果path中已经有了这个元素就continue
path.addLast(nums[i]);
backtracking(nums);
path.removeLast();
}
}
}
47.全排列 II
力扣题目链接
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
示例 1:
输入:nums = [1,1,2]
输出: [[1,1,2], [1,2,1], [2,1,1]]
示例 2:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
思路
排列后注意去重逻辑
同一树枝有两个重复元素,没关系,可以重复选取
但同一数层不能有两个重复元素,我们使用used集合标记

代码
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
if (nums == null || nums.length == 0) return res;
boolean[] used = new boolean[nums.length];
Arrays.fill(used,false);//设置used数组,初始化元素为false
Arrays.sort(nums);//注意把数组排序
backtracking(nums,used);
return res;
}
private void backtracking(int[] nums, boolean[] used){
if (path.size() == nums.length){
res.add(new ArrayList<>(path));//递归结束条件
return;
}
for (int i = 0; i < nums.length; i++){
if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) continue;
//这个元素和上一个相同不能直接continue,需要保证是同层才能continue
if (!used[i]){
used[i] = true;
path.addFirst(nums[i]);
backtracking(nums,used);
path.removeFirst();
used[i] = false;
}
}
}
}