代码随想录算法训练营第二十九天 | 491.递增子序列 46.全排列 47.全排列 II
一、力扣491.递增子序列
题目链接
思路:从数组中取递增子序列,不能排序,纵向递归要一直数组结束,所以不需要提前return,而且list的size只要大于2就可以收集到总集合中,纵向是不需要去重的,比如577,可以都要了。横向的话,是需要去重的,重复的数字是不可以用的,比如577,先取5,会拿到57,577,然后递归返回到第二层,会取第二个7变成57,所以横向要去重,可以在每次进入for之前设置一个hashset,遇到值就设置进去,如果当前值包含就要去重,想下递归每一次都是一个新集合,而横向遍历却会记录都加过哪些值以便去重。
class Solution {
List<List<Integer>> arrayLists = new ArrayList<>();
List<Integer> list = new ArrayList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
backTracking(nums, 0);
return arrayLists;
}
void backTracking(int[] nums, int startIndex) {
if (list.size() > 1) {
arrayLists.add(new ArrayList<>(list));
}
HashSet<Integer> set = new HashSet<>();
for (int i = startIndex; i < nums.length; i++) {
if (!list.isEmpty() && list.get(list.size() - 1) > nums[i] || set.contains(nums[i])) {
continue;
}
list.add(nums[i]);
set.add(nums[i]);
backTracking(nums, i + 1);
list.remove(list.size() - 1);
}
}
}
二、力扣46.全排列
题目链接
思路:终止条件list大小等于nums大小就满了可以终止。没有重复的不用去重,排列问题每次for都要从0开始所以也不要startIndex,纵向递归只需要不把已经添加的数加进去即可。
class Solution {
List<List<Integer>> arrayLists = new ArrayList<>();
List<Integer> list = new ArrayList<>();
boolean[] used;
public List<List<Integer>> permute(int[] nums) {
used = new boolean[nums.length];
backTracking(nums);
return arrayLists;
}
void backTracking(int[] nums) {
if (list.size() == nums.length) {
arrayLists.add(new ArrayList<>(list));
return;
}
for (int i = 0; i < nums.length; i++) {
if (used[i]) continue;
list.add(nums[i]);
used[i] = true;
backTracking(nums);
list.remove(list.size() - 1);
used[i] = false;
}
}
}
三、力扣47.全排列 II
题目链接
思路:上面那倒题目因为是不重复的,所以不用考虑横向,只用考虑纵向就行,用过的不要再加了,而这道题目,有重复值,所以纵向要考虑,横向也要考虑,横向的话如果前一个值和当前值相等并且没用过(回溯了)就要去重,纵向依然是当前值没用过才加入,用过的就要去重。
class Solution {
List<List<Integer>> arrayLists = new ArrayList<>();
List<Integer> list = new ArrayList<>();
boolean[] used;
public List<List<Integer>> permuteUnique(int[] nums) {
used = new boolean[nums.length];
Arrays.sort(nums);
Arrays.fill(used, false);
backTracking(nums);
return arrayLists;
}
void backTracking(int[] nums) {
if (list.size() == nums.length) {
arrayLists.add(new ArrayList<>(list));
return;
}
for (int i = 0; i < nums.length; i++) {
if (i > 0 && nums[i - 1] == nums[i] && !used[i-1]) continue;
if (!used[i]) {
list.add(nums[i]);
used[i] = true;
backTracking(nums);
list.remove(list.size() - 1);
used[i] = false;
}
}
}
}