全排列专题
题目描述:
全排列是面试中经常出现的题目,所以这边有需要做一下关于这一类的专题。首先我们从最简单的题目开始。给定一个数组,根据全排列的规律,找到当前排列的下一个全排列。
我们已知对于1,2,3排列而言,它的全排列依次如下:
1-2-3 1-3-2 2-1-3 2-3-1 3-1-2 3-2-1
例子:
以数组[1,3,8,7,6,5,4,2]为例子,我们首先找到第一次出现降序的位置3;再找到第一次比3大的位置4;交换二者的数据得到[1,4,8,7,6,5,3,2];再将4后面的数组逆序即可得到[1,4,2,3,5,6,7,8]
解题思路:
初看例子我们还无法看出前后排列之间的关系。通过网上资料查询我们可以知道,从当前排列得到下一个排列的算法:
- 首先我们从数组的末端开始遍历数组,直到第一次遇到num[i] < num[i + 1]的地方
- 然后我们从数组末尾开始找到第一次出现比num[i]大的数的位置num[j]
- 交换num[i]和num[j]
- 将i后面的数组逆序后即可以得到当前排列的下一个排列
代码如下:
|
|
题目描述2
在上述题目中,我们没有考虑到关于在数组中可能存在重复数字的情况。现在给定一个数组,其中可能包含重复数字,要求返回所有不重复的可能的排列结果。上文中所述的方法恰好排除了这种可能重复出现的情况。所以基本还是沿用上一题的思路来解决这个问题。
代码如下:
|
|
题目描述3:
在以上的解题过程中用的都是非递归的方法实现,现在要求使用递归的方式实现找到某个数组的全排列。主要的思路是用begin来标记当前要确定的排列位置,然后在从begin到数组末尾的各个数和begin进行交换得到不同的可能排列,而后进行下一个位置的寻找。遍历的停止条件是当前遍历位置大于数组长度的时候。需要注意的是,我们在遍历后需要进行一步回溯。比如在找到[1,3,2]后我们需要交换3和2变回[1,2,3],便于下一步进行得到[2,1,3]结果。
代码如下:
|
|
题目描述4
在使用递归方法中,上述的方法无法解决出现重复数字的情况。比如[1,1,2]。因为在begin=0的情况中,i=0,1,2;而对于i=0得到[1,1,2]和i=1得到[1,1,2]得到的情况相同,后序的全排列重复。所以我们需要其他的方法来解决这个问题。其中之一就是哈希表。主要的思路是:我们用哈希表来记录数组中出现数字的次数,用vec来保存当前得到的全排列;每次从哈希表中找到一个数将其push到vec中,而哈希表中对应的出现个数减1;然后进入下一层递归即可。需要注意的是:我们每次push完一个数递归结束后,需要将这个数pop进行回溯;另外需要对哈希表中数字出现的个数进行增加和减少操作。
代码如下:
|
|