全排列算法
递归的思路
四个特性:
- 终止条件,否则陷入死循环
- 子问题规模比原问题小
- 子问题可以通过递归再次求解
- 子问题的解应该能组合成整个问题的解
全排列的过程:
对于字符串abc
- 首先固定字符a,得到后面两个字符bc的全排列;
- 轮到字符a与a后面的第一个字符即字符b交换位置,得到bac,对于后面两个字符全排列;
- 轮到字符a与a后面的第二个字符即字符c交换位置,但是此时在把字符c与第一个位置的字符进行交换前,要先把b和a交换回来,然后再拿字符c和字符a进行交换得到cba,再次固定字符c,对ba进行全排列;
- 已经知道怎么求三个字符串的排序,那么固定一个字符求另外两个字符的排序就是递归;
去掉重复的全排列
由于全排列就是从第一个数字起,每个数分别与它后面的数字交换,我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这两个数就不交换了。例如abb,第一个数与后面两个数交换得bab,bba。然后abb中第二个数和第三个数相同,就不用交换了。但是对bab,第二个数和第三个数不同,则需要交换,得到bba。由于这里的bba和开始第一个数与第三个数交换的结果相同了,因此这个方法不行。
换种思维,对abb,第一个数a与第二个数b交换得到bab,然后考虑第一个数与第三个数交换,此时由于第三个数等于第二个数,所以第一个数就不再用与第三个数交换了。再考虑bab,它的第二个数与第三个数交换可以解决bba。此时全排列生成完毕!
去重的规则
去重的全排列就是从第一个数字起,每个数分别与它后面非重复出现的数字交换。