代码随想录刷题记录day26 递增序列+全排列
参考:代码随想录
491. 递增子序列
思想
同样涉及到了去重的逻辑,但是和之前的去重逻辑不太一样,这里不能对数组进行排序,排序后结果会改变。
比如原数组是 4 6 7 6 排序后是 4 6 7 7 ;排序后使得4 6 7 7 也是需要收集的一个结果了。
那么如何进行去重的逻辑呢? 用一个map 来记录是否使用过元素,同时 要满足递增的逻辑。
代码
class Solution {
List<List<Integer>> res=new ArrayList<>();
List<Integer> path=new ArrayList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
backTracking(nums,0);
return res;
}
public void backTracking(int []nums,int startIndex){
//回溯的终止条件
if(startIndex>nums.length){
return;
}
if(path.size()>1){
res.add(new ArrayList<>(path));
}
HashMap<Integer,Integer> map = new HashMap<>();
for(int i=startIndex;i<nums.length;i++){
if(!path.isEmpty() && nums[i]< path.get(path.size()-1)){
continue;
}
// 使用过了当前数字
if ( map.getOrDefault( nums[i],0 ) >=1 ){
continue;
}
map.put(nums[i],map.getOrDefault( nums[i],0 )+1);
path.add(nums[i]);
backTracking(nums,i+1);
path.remove(path.size()-1);
}
}
}
46. 全排列
思想
全排列问题不能使用startIndex 来去重,因为在同一层中,元素需要被重复选取。但是在同一树枝中元素不能被重复选取,所以还需要一个used数组来记录使用过的元素。
代码
class Solution {
List<List<Integer>> res=new ArrayList<>();
List<Integer> path=new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
int[] used=new int[nums.length];
backTracking(nums,used);
return res;
}
public void backTracking(int [] nums,int[] used ){
if(path.size()==nums.length){
res.add(new ArrayList<>(path));
return ;
}
for(int i=0;i<nums.length;i++){
if(used[i]==1) continue;
used[i]=1;
path.add(nums[i]);
backTracking(nums,used);
path.remove(path.size()-1);
used[i]=0;
}
}
}
47. 全排列 II
思想
这题和上一题的区别是数组中含有重复元素,所以涉及到树层的去重。
if(i>0 && nums[i-1]==nums[i] && used[i-1]==0) continue;
同时同一树枝上 选取过的元素不能再被选取了 用if(used[i]==1) continue;来判断
对于排列问题,树枝去重和树层去重都是可以的,但是树层去重的效率会更高一点。
代码
class Solution {
List<List<Integer>> res=new ArrayList<>();
List<Integer> path=new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
Arrays.sort(nums);
int[] used=new int[nums.length];
backTracking(nums,used);
return res;
}
public void backTracking(int [] nums,int[] 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-1]==nums[i] && used[i-1]==0) continue;
if(used[i]==1) continue;
used[i]=1;
path.add(nums[i]);
backTracking(nums,used);
path.remove(path.size()-1);
used[i]=0;
}
}
}