[LeetCode] 46. Permutations 全排列
Given a collection of distinct integers, return all possible permutations.
Example:
Input: [1,2,3]
Output:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
这道题是求全排列问题,给的输入数组没有重复项,这跟之前的那道 Combinations 和类似,解法基本相同,但是不同点在于那道不同的数字顺序只算一种,是一道典型的组合题,而此题是求全排列问题,还是用递归 DFS 来求解。这里需要用到一个 visited 数组来标记某个数字是否访问过,然后在 DFS 递归函数从的循环应从头开始,而不是从 level 开始,这是和 Combinations 不同的地方,其余思路大体相同。这里再说下 level 吧,其本质是记录当前已经拼出的个数,一旦其达到了 nums 数组的长度,说明此时已经是一个全排列了,因为再加数字的话,就会超出。还有就是,为啥这里的 level 要从0开始遍历,因为这是求全排列,每个位置都可能放任意一个数字,这样会有个问题,数字有可能被重复使用,由于全排列是不能重复使用数字的,所以需要用一个 visited 数组来标记某个数字是否使用过,代码如下:
解法一:
class Solution {
public:
vector<vector<int>> permute(vector<int>& num) {
vector<vector<int>> res;
vector<int> out, visited(num.size(), );
permuteDFS(num, , visited, out, res);
return res;
}
void permuteDFS(vector<int>& num, int level, vector<int>& visited, vector<int>& out, vector<vector<int>>& res) {
if (level == num.size()) {res.push_back(out); return;}
for (int i = ; i < num.size(); ++i) {
if (visited[i] == ) continue;
visited[i] = ;
out.push_back(num[i]);
permuteDFS(num, level + , visited, out, res);
out.pop_back();
visited[i] = ;
}
}
};
上述解法的最终生成顺序为:[[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]] 。
还有一种递归的写法,更简单一些,这里是每次交换 num 里面的两个数字,经过递归可以生成所有的排列情况。这里你可能注意到,为啥在递归函数中, push_back() 了之后没有返回呢,而解法一或者是 Combinations 的递归解法在更新结果 res 后都 return 了呢?其实如果你仔细看代码的话,此时 start 已经大于等于 num.size() 了,而下面的 for 循环的i是从 start 开始的,根本就不会执行 for 循环里的内容,就相当于 return 了,博主偷懒就没写了。但其实为了避免混淆,最好还是加上,免得和前面的搞混了,代码如下:
解法二:
class Solution {
public:
vector<vector<int>> permute(vector<int>& num) {
vector<vector<int>> res;
permuteDFS(num, , res);
return res;
}
void permuteDFS(vector<int>& num, int start, vector<vector<int>>& res) {
if (start >= num.size()) res.push_back(num);
for (int i = start; i < num.size(); ++i) {
swap(num[start], num[i]);
permuteDFS(num, start + , res);
swap(num[start], num[i]);
}
}
};
上述解法的最终生成顺序为:[[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,2,1], [3,1,2]]
最后再来看一种方法,这种方法是 CareerCup 书上的方法,也挺不错的,这道题是思想是这样的:
当 n=1 时,数组中只有一个数 a1,其全排列只有一种,即为 a1
当 n=2 时,数组中此时有 a1a2,其全排列有两种,a1a2 和 a2a1,那么此时考虑和上面那种情况的关系,可以发现,其实就是在 a1 的前后两个位置分别加入了 a2
当 n=3 时,数组中有 a1a2a3,此时全排列有六种,分别为 a1a2a3, a1a3a2, a2a1a3, a2a3a1, a3a1a2, 和 a3a2a1。那么根据上面的结论,实际上是在 a1a2 和 a2a1 的基础上在不同的位置上加入 a3 而得到的。
_ a1 _ a2 _ : a3a1a2, a1a3a2, a1a2a3
_ a2 _ a1 _ : a3a2a1, a2a3a1, a2a1a3
解法三:
class Solution {
public:
vector<vector<int>> permute(vector<int>& num) {
if (num.empty()) return vector<vector<int>>(, vector<int>());
vector<vector<int>> res;
int first = num[];
num.erase(num.begin());
vector<vector<int>> words = permute(num);
for (auto &a : words) {
for (int i = ; i <= a.size(); ++i) {
a.insert(a.begin() + i, first);
res.push_back(a);
a.erase(a.begin() + i);
}
}
return res;
}
};
上述解法的最终生成顺序为:[[1,2,3], [2,1,3], [2,3,1], [1,3,2], [3,1,2], [3,2,1]]
上面的三种解法都是递归的,我们也可以使用迭代的方法来做。其实下面这个解法就上面解法的迭代写法,核心思路都是一样的,都是在现有的排列的基础上,每个空位插入一个数字,从而生成各种的全排列的情况,参见代码如下:
解法四:
class Solution {
public:
vector<vector<int>> permute(vector<int>& num) {
vector<vector<int>> res{{}};
for (int a : num) {
for (int k = res.size(); k > ; --k) {
vector<int> t = res.front();
res.erase(res.begin());
for (int i = ; i <= t.size(); ++i) {
vector<int> one = t;
one.insert(one.begin() + i, a);
res.push_back(one);
}
}
}
return res;
}
};
上述解法的最终生成顺序为:[[3,2,1], [2,3,1], [2,1,3], [3,1,2], [1,3,2], [1,2,3]]
下面这种解法就有些耍赖了,用了 STL 的内置函数 next_permutation(),专门就是用来返回下一个全排列,耳边又回响起了诸葛孔明的名言,我从未见过如此...投机取巧...的解法!
解法五:
class Solution {
public:
vector<vector<int>> permute(vector<int>& num) {
vector<vector<int>> res;
sort(num.begin(), num.end());
res.push_back(num);
while (next_permutation(num.begin(), num.end())) {
res.push_back(num);
}
return res;
}
};
上述解法的最终生成顺序为:[[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
Github 同步地址:
https://github.com/grandyang/leetcode/issues/46
类似题目:
参考资料:
https://leetcode.com/problems/permutations/
https://leetcode.com/problems/permutations/discuss/18462/Share-my-three-different-solutions
https://leetcode.com/problems/permutations/discuss/18255/Share-my-short-iterative-JAVA-solution
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] 46. Permutations 全排列的更多相关文章
- [leetcode]46. Permutations全排列(给定序列无重复元素)
Given a collection of distinct integers, return all possible permutations. Input: [1,2,3] Output: [ ...
- LeetCode - 46. Permutations
46. Permutations Problem's Link -------------------------------------------------------------------- ...
- LeetCode 46 Permutations(全排列问题)
题目链接:https://leetcode.com/problems/permutations/?tab=Description Problem:给出一个数组(数组中的元素均不相同),求出这个数组 ...
- 【LeetCode】Permutations(全排列)
这道题是LeetCode里的第46道题. 题目要求: 给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3 ...
- [leetcode]47. Permutations全排列(给定序列有重复元素)
Given a collection of numbers that might contain duplicates, return all possible unique permutations ...
- 46. Permutations (全排列)
Given a collection of distinct numbers, return all possible permutations. For example,[1,2,3] have t ...
- 46 Permutations(全排列Medium)
题目意思:全排列 思路:其实看这题目意思,是不太希望用递归的,不过还是用了递归,非递归的以后再搞吧 ps:vector这玩意不能随便返回,开始递归方法用vector,直接到500ms,换成void,到 ...
- LeetCode 046 Permutations 全排列
Given a collection of distinct numbers, return all possible permutations.For example,[1,2,3] have th ...
- [LeetCode] 47. Permutations II 全排列 II
Given a collection of numbers that might contain duplicates, return all possible unique permutations ...
随机推荐
- 【shell脚本】检测当前用户是否为超级管理员===checkRoot.sh
检测当前用户是否为超级管理员,是则使用yum安装vsftpd,不是则输出提示信息 脚本赋予执行权限 [root@VM_0_10_centos shellScript]# chmod a+x check ...
- 六、显式锁和AQS
显式锁和AQS 一.显式锁 Synchronized 关键字结合对象的监视器,JVM 为我们提供了一种『内置锁』的语义,这种锁很简便,不需要我们关心加锁和释放锁的过程,我们只需要告诉虚拟机哪些代码 ...
- js生成条形码
生成条形码 <body> <div> <img id="ma"/> </div> </body> </html&g ...
- tensorflow: arg_scope()
with arg_scope(): 1.允许我们设定一些共享参数,并将其进行保存,必要时还可以嵌套覆盖 2.在指定的函数调用时,可以将一些默认参数塞进去. 接下来看一个tensorflow自带的例子. ...
- Microsoft.Windows.Controls.Ribbon.RibbonWindow 碰到 AvalonDock出现的诡异现象
部分一 14年底进入目前公司时,领导准备开发一款新软件平台以取代原有平台.原平台采用C++Build开发界面(window c/s客户端) .Visual Studio(封装dll模块).过完年,领导 ...
- django中视图函数中装饰器
方法一 给指定方法加 from django.utils.decorators import method_decorator class xx(View): @method_decorator(装饰 ...
- Java向服务器上传图片
在比较绚丽多彩的网站或者业务逻辑比较丰富的程序设计过程中,图片的相关操作时必不少的,尤其时图片的上传.还没有彻底摆脱纸质办公可能需要将纸质的文件备份上传,网站的建设可能需要上传用户头像.图片描述等等, ...
- PHP 类/对象函数
PHP类/对象函数是PHP核心的一部分,无需要安装就可以使用. 函数名称 描述 __autoload 尝试加载未定义的类 class_alias 为一个类创建别名 class_exists 检查类是否 ...
- 英语_金丝楠是紫楠(phoebeSheareri)的别名
姚黄魏紫俱凋零--红木家具今古谈(连载七) [上海木业网]楠木品种包括闽楠.细叶楠.红毛山楠.滇楠.白楠.紫楠.乌心楠.桢楠.水楠.香楠等二百余种之多,1997年的木材国家标准中就列入了八种.某些售卖 ...
- [20190507]sga_target=0注意修改_kghdsidx_count设置.txt
[20190507]sga_target=0注意修改_kghdsidx_count设置.txt --//昨天遇到一例视图定义太复杂导致长时间分析sql语句出现library cache lock等待事 ...