491.递增子序列
第一想法
和之前做的很像,额外注意三点:树层剪枝,元素递增只要保证当前收集元素大于等于最后一i个收集的元素可以,否则直接剪枝。如果递增收集元素提前并且itemPath.size()>=2 才可以收集。’
发现一个大坑:我们要做树层剪枝需要将原数组排序,但是题目要求原数组顺序是不能动的。
代码随想录
在节点上取,与子集不相同的是要求size()>=2
剪枝:树层重复,在可选数组中当前遍历元素小于已经加入itemPath中的最后一个元素
递归中用去重,也就是每层(每调用一层函数)设置一个set去重。重复并或者不递增时砍掉分枝后,该层还可以往后继续遍历,所以选择continue
代码
class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> itemPath = new ArrayList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
getPath(nums,0);
return result;
}
public void getPath(int[] nums,int startIndex){
if(itemPath.size()>=2){
result.add(new ArrayList<>(itemPath));
}
if(startIndex>=nums.length){
return;
}
HashSet<Integer> usedSet = new HashSet<>();
for(int i = startIndex;i<nums.length;i++){
if(!itemPath.isEmpty()&&nums[i]<itemPath.get(itemPath.size()-1)||usedSet.contains(nums[i])){
continue;
}else{
usedSet.add(nums[i]);
itemPath.add(nums[i]);
getPath(nums,i+1);
itemPath.remove(itemPath.size()-1);
}
}
}
}
46.全排列
第一想法
纸上画图之后发现不能用startIndex保证不取已经取过的前面的元素,在可选数组中,挑选当前遍历元素,那么剩余的元素都可以选。比如[1,2,3],遍历元素2时,剩余的元素[1,3]也是可以选的。所以需要传入参数curIndex来跳过上层遍历元素即可。
发现仅传入curIndex,不传入startIndex无法保证子层的数组分割
代码随想录
感觉排列问题是用used数组树枝去重;组合问题(无重复元素)的用startIndex去重,有重复元素的要做数层去重(used数组或者hashset)
代码
class Solution {
List<List<Integer>> results = new ArrayList<>();
List<Integer> itemPath = new ArrayList<>();
int[] used;
public List<List<Integer>> permute(int[] nums) {
used = new int[nums.length];
getPath(nums);
return results;
}
public void getPath(int[] nums){
if(itemPath.size()==nums.length){
results.add(new ArrayList<>(itemPath));
return;
}
for(int i = 0;i<nums.length;i++){
if(used[i]==1){
continue;
}else{
used[i]=1;
itemPath.add(nums[i]);
getPath(nums);
used[i]=0;
itemPath.remove(itemPath.size()-1);
}
}
}
}
47.全排列II
第一想法
用used实现树层去重(used[i]==used[i-1])同时实现排列(used[i]==true)。数组排序对求解全排列结果不影响
代码随想录
关键的是去重代码,used[i-1] = false 或者 used[i-1] = true
如果要对树层中前一位去重,就用used[i - 1] == false
,如果要对树枝前一位去重用used[i - 1] == true
。详见代码随想录
真正处理逻辑要判断used[i]==false才可以,等到一位没有用过的元素。
代码
class Solution {
List<List<Integer>> results = new ArrayList<>();
List<Integer> itemPath = new ArrayList<>();
boolean[] used;
public List<List<Integer>> permuteUnique(int[] nums) {
Arrays.sort(nums);
used = new boolean[nums.length];
getPath(nums);
return results;
}
public void getPath(int[] nums){
if(itemPath.size()==nums.length){
results.add(new ArrayList<>(itemPath));
return;
}
for(int i = 0;i<nums.length;i++){
if(i>0&&nums[i]==nums[i-1]&&used[i-1]==false) {
continue;
}else if(used[i]==false){
used[i]=true;
itemPath.add(nums[i]);
getPath(nums);
used[i]=false;
itemPath.remove(itemPath.size()-1);
}
}
}
}