力扣46题、47题(回溯算法,全排列)
46、全排列
基本思想:
回溯算法
具体实现:
与组合问题的不同,不在for循环中使用stratindex
因为全排列问题每次都要从头搜索,例如元素1在[1,2]中已经使用过了,但是在[2,1]中还要再使用一次1。
但是路径中出现过的数字,就不要再添加进来了

代码:
class Solution { List<List<Integer>> result = new ArrayList<>(); LinkedList<Integer> path = new LinkedList<>(); public List<List<Integer>> permute(int[] nums) { if (nums.length == 0) return result; backtrack(nums, path); return result; } public void backtrack(int[] nums, LinkedList<Integer> path) { if (path.size() == nums.length) { result.add(new ArrayList<>(path)); } for (int i =0; i < nums.length; i++) { // 如果path中已有,则跳过 if (path.contains(nums[i])) { continue; } path.add(nums[i]); backtrack(nums, path); path.removeLast(); } } }

class Solution { List<List<Integer>> result = new ArrayList<>(); LinkedList<Integer> track= new LinkedList<>(); boolean[] used; public List<List<Integer>> permute(int[] nums) { used = new boolean[nums.length]; traversal(nums); return result; } public void traversal(int[] nums) { if (track.size() == nums.length) { result.add(new ArrayList<>(track)); return; } for (int i = 0; i < nums.length; i++) { if (used[i]) continue; //同一树层不可能重复,因为数组内没有重复元素 //同一树枝选取元素,上一层选过的这一层可能会重复选取 //碰到用过的元素就跳过这个元素,找下一个元素 used[i] = true; track.add(nums[i]); traversal(nums); used[i] = false; track.removeLast(); } } }
47、全排列II
具体实现:

代码:
class Solution { //存放结果 List<List<Integer>> result = new ArrayList<>(); //暂存结果 List<Integer> path = new ArrayList<>(); public List<List<Integer>> permuteUnique(int[] nums) { boolean[] used = new boolean[nums.length]; Arrays.fill(used, false); Arrays.sort(nums); backTrack(nums, used); return result; } private void backTrack(int[] nums, boolean[] used) { if (path.size() == nums.length) { result.add(new ArrayList<>(path)); return; } for (int i = 0; i < nums.length; i++) { // used[i - 1] == true,说明同⼀树⽀nums[i]与nums[i - 1]相等,允许 // used[i - 1] == false,说明同⼀树层nums[i]与nums[i - 1]相等,不允许 // 同⼀树层不允许有相等数字,同一树枝允许有相等元素,但不允许使用同一个元素 if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) { continue; } //如果同⼀树⽀上,used[i]==false说明nums[i]这个元素没使⽤过 if (used[i] == false) { used[i] = true;//标记同⼀树⽀nums[i]使⽤过,防止同一树支重复使用同一数字(相等数字可以再次使用) path.add(nums[i]); backTrack(nums, used); path.remove(path.size() - 1);//回溯,说明同⼀树层nums[i]使⽤过,防止下一树层重复 used[i] = false;//回溯 } } } }
class Solution { List<List<Integer>> result = new ArrayList<>(); LinkedList<Integer> track = new LinkedList<>(); boolean[] used; public List<List<Integer>> permuteUnique(int[] nums) { used = new boolean[nums.length]; Arrays.sort(nums); traversal(nums); return result; } public void traversal(int[] nums) { if (track.size() == nums.length) { result.add(new ArrayList<>(track)); return; } HashSet<Integer> hashSet = new HashSet<>();//层去重 for (int i = 0; i < nums.length; i++) { if (hashSet.contains(nums[i])) continue; if (used[i] == false) {//枝去重 hashSet.add(nums[i]);//记录元素 track.add(nums[i]); used[i] = true; traversal(nums); track.removeLast(); used[i] = false; } } } }
浙公网安备 33010602011771号