46. 全排列
文章目录
难度中等1089
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
回溯法:
以数组 [1, 2, 3] 的全排列为例。
先写以 11 开头的全排列,它们是:[1, 2, 3], [1, 3, 2],即 1 + [2, 3] 的全排列(注意:递归结构体现在这里);
再写以 22 开头的全排列,它们是:[2, 1, 3], [2, 3, 1],即 2 + [1, 3] 的全排列;
最后写以 33 开头的全排列,它们是:[3, 1, 2], [3, 2, 1],即 3 + [1, 2] 的全排列。
递归的终止条件是: 一个排列中的数字已经选够了
状态变量:
-
递归到第几层 depth
Deque<Integer> path = new ArrayDeque<Integer>();
-
已经选了哪些数 path
-
布尔数组 use 初始化的时候都为 false 表示这些数还没有被选择,当我们选定一个数的时候,就将这个数组的相应位置设置为 true ,这样在考虑下一个位置的时候,就能够以 O(1)O(1) 的时间复杂度判断这个数是否被选择过,这是一种「以空间换时间」的思想。
package com.nie.OneJanLC;/*
*
*@auth wenzhao
*@date 2021/1/16 23:58
*/
import java.util.*;
public class LEE046L {
class Solution {
public List<List<Integer>> permute(int[] nums) {
int len = nums.length;
if (len == 0) {
return null;
}
List<List<Integer>> res = new ArrayList<>();
boolean[] use = new boolean[len];
Deque<Integer> path = new ArrayDeque<Integer>();
dfs(nums, len, 0, use, path, res);
return res;
}
private void dfs(int[] nums, int len, int depth, boolean[] use, Deque<Integer> path, List<List<Integer>> res) {
if (depth == len) {
res.add(new ArrayList<>(path));
return;
}
// 在非叶子结点处,产生不同的分支,这一操作的语义是:
// 在还未选择的数中依次选择一个元素作为下一个位置的元素,这显然得通过一个循环实现。
for (int i = 0; i < len; i++) {
if (use[i]) {
continue;
}
path.add(nums[i]);
use[i] = true;
dfs(nums, len, depth + 1, use, path, res);
// 注意:下面这两行代码发生 「回溯」,回溯发生在从 深层结点 回到 浅层结点 的过程,
// 代码在形式上和递归之前是对称的
use[i] = false;
path.removeLast();
}
}
}
}
47. 全排列 II
难度中等566
给定一个可包含重复数字的序列 nums
,按任意顺序 返回所有不重复的全排列。
示例 1:
输入:nums = [1,1,2]
输出:
[[1,1,2],
[1,2,1],
[2,1,1]]
示例 2:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
在回溯处理前:必须先进行排序
- 在图中 ② 处,搜索的数也和上一次一样,但是上一次的 1 还在使用中;
- 在图中 ① 处,搜索的数也和上一次一样,但是上一次的 1 刚刚被撤销,正是因为刚被撤销,下面的搜索中还会使用到,因此会产生重复,剪掉的就应该是这样的分支。
注 在回溯处理前:必须先进行排序
所以在46题上基础上加上:
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1]!=flase) {
continue;
}
package com.nie.OneJanLC;/*
*
*@auth wenzhao
*@date 2021/1/16 23:58
*/
import java.util.*;
public class LEE047L {
class Solution {
public List<List<Integer>> permute(int[] nums) {
int len = nums.length;
if (len == 0) {
return null;
}
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
boolean[] use = new boolean[len];
Deque<Integer> path = new ArrayDeque<>();
dfs(nums, len, 0, use, path, res);
return res;
}
private void dfs(int[] nums, int len, int depth, boolean[] use, Deque<Integer> path, List<List<Integer>> res) {
if (depth == len) {
res.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < len; i++) {
if (i > 0 && use[i] == use[i - 1] && use[i - 1] != false) {
continue;
}
if (use[i]) {
continue;
}
path.add(nums[i]);
use[i] = true;
dfs(nums, len, depth + 1, use, path, res);
use[i] = false;
path.removeLast();
}
}
}
}
版权声明:本文为qq_44236958原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。