力扣 46. 全排列 [设置/不设置 标志数组]
给定一个不含重复数字的数组 nums
,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
示例 1:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
示例 2:
输入:nums = [0,1]
输出:[[0,1],[1,0]]
示例 3:
输入:nums = [1]
输出:[[1]]
提示:
1 <= nums.length <= 6
-10 <= nums[i] <= 10
nums
中的所有整数 互不相同
解1:设置标志数组+额外存储当前路径#
最简单的方法就是基础的DFS,通过设置标志数组flag
来记录已经元素是否选取过。
下图是以[0,1]示意递归过程:
查看代码
class Solution {
public:
vector<vector<int>> res;
bool flag[6]={false};
vector<int> cur;
void dfs(vector<int> nums){
if(nums.size()==cur.size())//cur排满了
{
res.emplace_back(cur);
return;
}
for(int i=0;i<nums.size();i++){
if(!flag[i]){//之前没有选择过
cur.emplace_back(nums[i]);//选择当前
flag[i]=!flag[i];//修改标志位
dfs(nums);//进入递归
flag[i]=!flag[i];//恢复标志位
cur.pop_back();//退回之前的状态,清除之前的选择
}
}
}
vector<vector<int>> permute(vector<int>& nums) {
dfs(nums);
return res;
}
};
解2:不设置标志数组+不额外存储当前路径#
来自官方题解。
可以节约掉标志数组,将原nums
数组以下标idx
划分为两个部分,左侧为已经选取的,右侧为没有选取的。在递归的时候动态维护Nums
。
则Nums[0到idx-1]
是已经选取过的数,而右边的[idx到len-1]
是没有选取的,那么for
循环可以以idx
开始,i=idx:len-1
,因为我们需要从[idx到len-1]
这个范围选取一个元素,而元素一旦选取需要放在左边,所以我们选取当前元素i
时,我们交换下标idx和下标i
的元素值,这样每次选取下标i
元素时,通过交换就可以维护Nums
为选取的序列,当然,同上面的解法1,在出dfs
后需要还原这个选取。
下图是以[0,1]示意递归过程:
查看代码
class Solution {
public:
vector<vector<int>> res;
// bool flag[6]={false};
vector<int> cur;
void dfs(vector<int> outputs,int len,int idx){
if(len==idx)//cur排满了
{
res.emplace_back(outputs);
return;
}
for(int i=idx;i<len;i++){
swap(outputs[i],outputs[idx]);//交换
dfs(outputs,len,idx+1);
swap(outputs[i],outputs[idx]);//恢复
}
}
vector<vector<int>> permute(vector<int>& nums) {
dfs(nums,nums.size(),0);
return res;
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步