491.递增子序列
思路:
不能回头,所以需要startindex控制循环开始位置;同一层不能选相同的元素,但数组是无序的且不能排序,所以需要每层都需要建立一个数组记录用过的数字。
代码:
class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> paths = new ArrayList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
backtracking(nums, 0);
return res;
}
private void backtracking(int[] nums, int startindex){
if(paths.size() > 1){
res.add(new ArrayList<>(paths));
//取树上的节点,不需要return
}
int[] used = new int[201];//每一层都需要数组来记录用过的数字
for(int i = startindex; i < nums.length; i++){
if(!paths.isEmpty() && nums[i] < paths.get(paths.size() - 1) || used[nums[i] + 100] == 1){
continue;//当前数小于paths最后一个数或这个数在本层用过(used[0] 记录-100,所以要+100)
}
used[nums[i] + 100] = 1;//记录用过的数
paths.add(nums[i]);
backtracking(nums, i + 1);//因为选序列,不能回头,所以需要startindex控制起始位置
paths.remove(paths.size() - 1);
}
}
}
需要注意的点:
见代码
46.全排列
思路:
在进行每一步选元素前需要判断paths中是否有这个元素,无需考虑顺序(不用startindex)。
代码:
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> paths = new LinkedList<>();
public List<List<Integer>> permute(int[] nums) {
backtracking(nums);
return res;
}
private void backtracking(int[] nums){//顺序可以不同,但选过的元素不能选
if(paths.size() == nums.length){
res.add(new ArrayList<>(paths));
return;
}
for(int i = 0; i < nums.length; i++){
if(paths.contains(nums[i])){
continue;
}
paths.add(nums[i]);
backtracking(nums);
paths.removeLast();
}
}
}
需要注意的点:
1、检查paths(LinkedList)中是否含有某元素:paths.contains(元素)。
47.全排列 II
思路:
因为有重复元素,不但要对用过位置进行跳过,重复的元素每层只能选一个。
代码:
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> paths = new LinkedList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
Arrays.sort(nums);
int[] check = new int[nums.length];
backtracking(nums, check);
return res;
}
private void backtracking(int[] nums, int[] check){
if(paths.size() == nums.length){
res.add(new ArrayList<>(paths));
return;
}
for(int i = 0; i < nums.length; i++){
//当遇到选过的元素(用check[]来记录,用过的位置记为1。
//或碰到连续相同的元素,(相同元素)前面位置只有上一步被选过才能在这一步选这个(相同)元素)
//从而保证同一层相同的元素只能选一个(保证每一次只选择选过元素后面一个)
if(check[i] == 1 || (i > 0 && nums[i] == nums[i - 1] && check[i - 1] != 1)) continue;
paths.add(nums[i]);
check[i] = 1;//标记选过的位置
backtracking(nums, check);
paths.removeLast();
check[i] = 0;
}
}
}
需要注意的点:
1、同层相同元素去重,注意对代码的理解:把相同的元素看成整体,每层选有相同元素的数时,指定选上一层选过相同数的后一个位置,除此之外的跳过。