给定一组互不相同的数字,返回所有可能的排列。
难度
Medium
个人题解
方法一
stl 算法库已经提供了排列相关的算法next_permutation
以及prev_permutation
,所以首先想到的方法是使用next_permutation
试试规模如何。
next_permutation
从当前排列产生下一个排列需要如下4步:
-
从后往前,找到第一个连续的顺序对 (a, b);
-
从后往前,找到第一个比 a 大的数 c;
-
交换 a 和 c;
-
反转介于 a 和 c 之间的数。
时间复杂度为 O(n)。
全排列一共有 n! 种,产生每种排列的复杂度为 O(n),因而总时间复杂度为 O(n*n!)。需要特别注意的是,next_permutation
是按顺序进行的,所以只有初始状态最小才可能产生所有的排列;因而需要先对序列进行排序或者综合使用 next_permutation
以及 prev_permutation
。
方法二
使用深度优先搜索,开一个与序列元素一一对应的布尔数组unsel[]
,如果序列中某一个元素已经被选择过了,那么对应的布尔值为false
,否则为true
。
那么对于一个长度为n
的序列,其搜索树每一层的节点数分别为:1、n、n * (n - 1)、n * (n - 1) * (n - 2)、...、n!、n!,边数分别为:n、n * (n - 1)、n * (n - 1) * (n - 2)、...、n!、n!,每一个叶子节点导出一种排列。在布尔数组的基础上建立链表,将所有值为true
的节点连接起来,那么从一个节点转移到下一个节点的复杂度为 O(1),因而时间复杂度为 (1 + 2 * (n + n * (n - 1) + ... + n! + n!)) * O(1) = (1 + 2e * n!) * O(1) = O(n!)。
源代码
方法一
方法二