由于需要保证数组的顺序,这题不像[[90. Subsets II]]那般能sort,所以用了map来去重
import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; public class IncreasingSubsequences { List<List<Integer>> result = new ArrayList<>(); LinkedList<Integer> path = new LinkedList<>(); public List<List<Integer>> findSubsequences(int[] nums) { backTracking(nums, 0); return result; } private void backTracking(int[] nums, int startIndex){ if(path.size() > 1){ result.add(new ArrayList<>(path)); // 注意这里不要加return,要取树上的节点 } //说明:map是记录本层元素是否重复使用,新的一层map都会重新定义(清空), //所以要知道map只负责本层!map与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) || map.getOrDefault(nums[i], 0) == 1){// 使用过了当前数字 continue; } // 使用过了当前数字就把对应数字的value设置1,没有使用就为0 map.put(nums[i], map.getOrDefault(nums[i], 0) +1); path.add(nums[i]);// 子集收集元素 backTracking(nums, i + 1); path.removeLast(); } } }
import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class Permutations { List<List<Integer>> result = new ArrayList<>(); LinkedList<Integer> path = new LinkedList<>(); int[] used; public List<List<Integer>> permute(int[] nums) { //used数组:其实就是记录此时path里都有哪些元素使用了, //等于1为已使用,等于0为未使用。一个排列里一个元素只能使用一次。 used = new int[nums.length]; backTracking(nums, used); return result; } private void backTracking(int[] nums, int[] used){ //收集元素的数组path的大小达到和nums数组一样大的时候, //说明找到了一个全排列,也表示到达了叶子节点。 if(path.size() == nums.length){ result.add(new ArrayList<>(path)); return; } //排列问题,每次都要从头开始搜索, //例如元素1在[1,2]中已经使用过了,但是在[2,1]中还要再使用一次1。 for(int i =0; i < nums.length; i++){ //等于1为已使用,即path里已经收录的元素 if(used[i] == 1){ continue; } used[i] = 1;//标记为已使用 path.add(nums[i]); backTracking(nums, used); //回溯 used[i] = 0; path.removeLast(); } } }
import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; public class PermutationsII { List<List<Integer>> result = new ArrayList<>(); LinkedList<Integer> path = new LinkedList<>(); int[] used; public List<List<Integer>> permuteUnique(int[] nums) { Arrays.sort(nums);//去重要排序,保证相同的元素排到一起 used = new int[nums.length]; backTracking(nums,used); return result; } private void backTracking(int[] nums, int[] used){ if(path.size() == nums.length){ result.add(new ArrayList<>(path)); return; } for(int i = 0; i < nums.length; i++){ //树层去重 if(i > 0 && nums[i] == nums[i - 1] && used[i - 1] ==0){ continue; } //等于1为已使用,即path里已经收录的元素 if(used[i] == 1) continue;//取过的数标志为1后就跳过,取没有取过的数了 used[i] = 1;//标记为已使用 path.add(nums[i]); backTracking(nums, used); used[i] =0; path.removeLast(); } } }