给出一组数字,返回该组数字的所有排列
例如:
[1,2,3]的所有排列如下
[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2], [3,2,1].
(以数字在数组中的位置靠前为优先级,按字典序排列输出。)
[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2], [3,2,1].
(以数字在数组中的位置靠前为优先级,按字典序排列输出。)
数据范围:数字个数
要求:空间复杂度
,时间复杂度
[1,2,3]
[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
[1]
[[1]]
class Solution {
public:
vector<vector<int> > permute(vector<int> &num) {
vector<vector<int> > res;
permutation(res,num,0);
return res;
}
void permutation(vector<vector<int> > &res,vector<int> &num,int s)
{
if(s == num.size()-1)
res.push_back(num);
else{
for(int i=s;i<num.size();i++)
{
swap(num[s],num[i]);
permutation(res,num,s+1);
swap(num[s],num[i]);
}
}
}
}; /**
* 46. Permutations
* @author Jacob
* 题意:求数组的全排列
*/
public class Demo1 {
ArrayList<ArrayList<Integer>> res;
public ArrayList<ArrayList<Integer>> permute(int[] nums) {
res = new ArrayList<ArrayList<Integer>>();
if (nums == null || nums.length < 1)
return res;
//对数组元素进行从小到大排序
Arrays.sort(nums);
ArrayList<Integer> list = new ArrayList<Integer>();
solve(list, nums);
return res;
}
private void solve(ArrayList<Integer> list, int[] nums) {
if (list.size() == nums.length) {
res.add(new ArrayList<Integer>(list));
return;
}
for (int i = 0; i < nums.length; i++) {
if (!list.contains(nums[i])) {
list.add(nums[i]);
solve(list, nums);
list.remove(list.size() - 1);
}
}
}
} import java.util.*;
public class Solution {
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
ArrayList<Integer> ls = new ArrayList<>();
public ArrayList<ArrayList<Integer>> permute(int[] num) {
int[] used = new int[num.length];
dfs(num,used);
return res;
}
private void dfs(int[] a,int[] used) {
if(ls.size() == a.length) {
res.add(new ArrayList<>(ls));
return;
}
for(int i = 0; i < a.length; i++) {
if(used[i] == 1) continue;
used[i] = 1;
ls.add(a[i]);
dfs(a,used);
used[i] = 0;
ls.remove(ls.size()-1);
}
}
} 做烂了的回溯
class Solution {
public:
void dfs(int cur, vector<int> &tmp, vector<int> &taken, vector<int> &num,
vector<vector<int> > &res){
int n = num.size();
if(tmp.size() == n){res.push_back(tmp);return;}
for(int i = 0; i < n; i++){
if(!taken[i]){
taken[i] = 1;
tmp.push_back(num[i]);
dfs(i+1, tmp, taken, num, res);
tmp.pop_back();
taken[i] = 0;
}
}
}
vector<vector<int> > permute(vector<int> &num) {
vector<int> tmp;
vector<int> taken(num.size(), 0);
vector<vector<int> > res;
dfs(0, tmp, taken, num, res);
return res;
}
};
class Solution {
public:
vector<vector<int> > permute(vector<int> &num) {
// 时间复杂度O(N!),空间复杂度O(N!)
vector<vector<int>> res;
vector<int> path;
sort(num.begin(), num.end());
recursion(num, path, res);
return res;
}
void recursion(vector<int> &num, vector<int> &path, vector<vector<int>> &res) {
if (num.empty()) {
res.push_back(path);
return;
}
for (int i = 0; i < num.size(); ++i) {
path.push_back(num[i]);
vector<int> tmp(num); // 拷贝一份,删除path中加入的num[i]
tmp.erase(tmp.begin() + i);
recursion(tmp, path, res);
path.pop_back();
}
}
}; 递归 + 回溯 不回溯的话num还停留在上一次递归排列的状态,可能会导致出现漏排的情况
时间复杂度:O(n!) 空间复杂度:O(n) 递归栈的深度
还有注意添加排列好的num时使用深拷贝
import copy
class Solution:
def recursion(self, num, res, index):
if index == len(num) - 1:
res.append(copy.deepcopy(num))
else:
for i in range(index, len(num)):
temp = num[i]
num[i] = num[index]
num[index] = temp
self.recursion(num, res, index+1)
temp = num[i]
num[i] = num[index]
num[index] = temp
def permute(self , num: List[int]) -> List[List[int]]:
num.sort()
res = []
self.recursion(num, res, 0)
return res
class Solution {
public:
void dfs(vector<int> &num,vector<vector<int>> &res,int begin)
{
if(begin == num.size())
res.push_back(num);
for(int i=begin;i<num.size();i++)
{
swap(num[i],num[begin]);
dfs(num,res,begin+1);
swap(num[i],num[begin]);
}
}
vector<vector<int> > permute(vector<int> &num)
{
vector<vector<int>> res;
if(num.size()==0)
return res;
sort(num.begin(),num.end());
dfs(num,res,0);
return res;
}
};
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param num int整型一维数组
* @return int整型ArrayList<ArrayList<>>
*/
public ArrayList<ArrayList<Integer>> permute (int[] num) {
// write code here
// 左程云老师讲过全排列的分支限界递归法解决不重复全排列问题
// 调用一个递归函数,这个递归函数负责对当前i位置的数字进行与i ~ num.length - 1中的位置依次互换,然后继续考察i + 1处的情况
// 算法的时间复杂度0(N!),额外空间复杂度0(N!)
// 用于记录所有路径的结果
ArrayList<ArrayList<Integer>> finalResults = new ArrayList<>();
// 调用这个递归函数,从num数组的0位置开始,将每一次找到的oneResult填进finalResult中
process(num, finalResults, 0);
// 返回最终的答案finalResults
return finalResults;
}
public void process(int[] num, ArrayList<ArrayList<Integer>> finalResults, int i) {
// 递归出口(底部)
if (i == num.length) {
// i越界了,说明整个数组遍历完毕了,将单个路径上的答案oneResult写入总答案finalResults中
// 踩坑点1:这里一定要【现场新创建】一个ArrayList放入答案中,如果提前在主方法创建好,那么随着每次递归的调用,finalResults里面的值也会被修改
ArrayList<Integer> oneResult = new ArrayList<>();
for (Integer n : num) {
oneResult.add(n);
}
finalResults.add(oneResult);
}
// 递归分支
for (int j = i; j < num.length; j++) {
// 将num[j]算入这次的结果中
swap(num, i, j);
// 在算入num[j]的基础上继续考察num数组中i+1往后的位置
process(num, finalResults, i + 1);
// 注意!恢复现场,继续尝试将将num[j+1]算入这次的结果中
// 踩坑点2:一定要【恢复现场】,要不然无法准确列出要分支的情况
swap(num, j, i);
}
}
// 数组元素交换函数
public void swap(int[] num, int i, int j) {
if (i == j) {
return;
}
int t = num[i];
num[i] = num[j];
num[j] = t;
}
} if(num.length == list.size()){
res.add(new ArrayList<>(list));
return;
} 递归回溯套路 public class Solution {
public ArrayList<ArrayList<Integer>> permute (int[] num) {
// write code here
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
LinkedList<Integer> list = new LinkedList<>();
boolean[] visit = new boolean[num.length];
dfs(num,res,list,visit);
return res;
}
private void dfs(int[] num, ArrayList<ArrayList<Integer>> res, LinkedList<Integer> list, boolean[] visit) {
if(num.length == list.size()){
res.add(new ArrayList<>(list));
return;
}
for(int i=0;i<num.length;i++){
if(visit[i]){
continue;
}
visit[i] = true;
list.add(num[i]);
dfs(num,res,list,visit);
list.pollLast();
visit[i] = false;
}
}
} class Solution {
public:
vector<vector<int> > permute(vector<int> &num) {
vector<vector<int>> res;
vector<int> ans;
recursion(num, ans, res);
return res;
}
void recursion(vector<int> vec, vector<int> &ans, vector<vector<int>> &res){
if(vec.size()==1){
ans.push_back(vec[0]);
res.push_back(ans);
ans.pop_back();
return;
}
for(int i : vec){
ans.push_back(i);
vector<int> newvec;
for (int j : vec){
if(i!=j) newvec.push_back(j);
}
recursion(newvec, ans, res);
ans.pop_back();
}
}
}; import java.util.*;
## 经典回溯
public class Solution {
List<Integer> list = new ArrayList<>();
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
public ArrayList<ArrayList<Integer>> permute(int[] num) {
Arrays.sort(num);
dfs(num,list);
return result;
}
private void dfs(int[] num,List<Integer> list){
if(list.size() == num.length){
result.add(new ArrayList<>(list));
return;
}
for(int i = 0; i < num.length; i ++){
if(list.contains(num[i])){
continue;
}
list.add(num[i]);
dfs(num,list);
list.remove(list.size() - 1);
}
}
} class Solution {
public:
void pushVec(vector<int> num, int index){
per.push_back(num);
for(int i = index; i < num.size()-1; ++ i){
for(int j = i+1; j < num.size(); ++ j){
swap(num[i],num[j]);
pushVec(num,i+1);
swap(num[i],num[j]);
}
}
}
vector<vector<int> > permute(vector<int> &num) {
pushVec(num,0);
return per;
}
private:
vector<vector<int> > per;
};
class Solution {
public:
//next_permutation:会取得[first,last)所标识之序列的下一个排列组合
//如果没有下一个排列组合,便返回false,否则返回true。
vector<vector<int> > permute(vector<int> &num) {
vector<vector<int> > res;
sort(num.begin(), num.end());
do
{
res.push_back(num);
} while (next_permutation(num.begin(),num.end()));
return res;
}
};
class Solution {
void permutation(vector<vector<int> >&ans,vector<int>& num,int l)
{
if(l == num.size()-1)
ans.push_back(num);
else
{
for(int i=l;i<num.size();i++)
{
swap(num[l],num[i]);
permutation(ans,num,l+1);
swap(num[l],num[i]);
}
}
}
public:
vector<vector<int> > permute(vector<int> &num) {
vector<vector<int> > ans;
permutation(ans,num,0);
return ans;
}
};
public ArrayList<ArrayList<Integer>> permute (int[] num) {
ArrayList<ArrayList<Integer>> ans=new ArrayList<>();
ArrayList<Integer> list=new ArrayList<>();
build(num,ans,list);
return ans;
}
public void build(int[] num,ArrayList<ArrayList<Integer>> ans,ArrayList<Integer> list){
if(list.size()==num.length){ //截至条件(终止条件)
ans.add(new ArrayList<>(list));
}
for(int i=0;i<num.length;i++){
if(list.contains(num[i])){ //因为这个题没有重复的数字, 所以当list中已经有了这个数字,那就剪枝
continue;
}
list.add(num[i]);
build(num,ans,list);
list.remove(list.size()-1);
}
}