全排列问题
问题描述:
给定一个数字的序列,返回其所有可能的全排列
例如:
给定{1,2,3} 返回{{1,2,3},{1,3,2},{2,1,3},{2,3,1},{3,1,2},{3,2,1}}
递归法
总思路:
一、 一堆数字的全排列等于固定一个数后,剩下的数字的全排列,因此可以递归。
二、 为方便起见,用123来示例下。123的全排列有123、132、213、231、312、321这六种。首先考虑213和321这二个数是如何得出的。显然这二个都是123中的1与后面两数交换得到的。然后可以将123的第二个数和每三个数交换得到132。同理可以根据213和321来得231和312。因此可以知道——全排列就是从第一个数字起每个数分别与它后面的数字交换。
根据规律,可以列出递归伪代码:
allArrange(str,k,m)
{
if k==m print;
for i=k to m {
swap(str,k,i); //k为第k个数
allArrange(str,k+1,m);
swap(str,k,i);} //注意,因为递归有回溯的过程,所以需要把数字重新调换回来变为”初始“的排列。
}
递归树理解如下:
每次固定几位数,最后只剩一位数,输出,在从后面递归返回上一层,交换再输出
代码部分
1.无重复数字时
class Solution {
public:
vector<vector<int>> answer;
void fun(vector<int>& nums,int star, int end)
{
if(star == end)
{
answer.push_back(nums);
}
else
{
for(int i=star; i<=end; i++)
{
swap(nums[i],nums[star]);
fun(nums,star+1,end);
swap(nums[i],nums[star]);
}
}
}
vector<vector<int>> permute(vector<int>& nums)
{
fun(nums,0,nums.size()-1);
return answer;
}
};
2.有重复数字时:
而有重复数字的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。用编程的话描述就是第i个数与第j个数交换时,要求[i,j)中没有与第j个数相等的数。
class Solution {
public:
bool IsSame(vector<int>& nums,int star, int end)
{
for(int i=star; i<end; i++)
{
if(nums[i]==nums[end])
return false;
}
return true;
}
vector<vector<int>> answer;
void fun(vector<int>& nums,int star, int end)
{
if(star == end)
{
answer.push_back(nums);
}
else
{
for(int i=star; i<=end; i++)
{
if( IsSame(nums,star,i) )
{
swap(nums[i],nums[star]);
fun(nums,star+1,end);
swap(nums[i],nums[star]);
}
}
}
}
vector<vector<int>> permuteUnique(vector<int>& nums)
{
fun(nums,0,nums.size()-1);
return answer;
}
};