剑指Offer_编程题——字符串的排列
题目描述:
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符串a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab,cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
具体要求:
时间限制: C/C++ 1秒,其他语言2秒
空间限制: C/C++32M,其他语言64M
具体思路:
思路一
这也是我们经常想到的思路,也就是固定交换法。即:先固定一个字母不变,通常固定在子串的首位,如abc固定a,对bc再进行全排列,bc串中固定b,对c进行全排列。交换即在a固定的情况下已经对bc子串进行了全排列之后,那么就将a与第二位的b交换变成bac,此时再回到了固定的步骤,只需固定b,对字串ac进行全排列。依此类推,直至交换完。这个是好想,但是有一个小坑需要我们注意,那就是有重复元素的情况,如aab,那么只需加一个判定条件,当交换的元素相同就无需进行交换,直接跳过即可。我们用python来实现这一思路。
class
代码效果图如图所示:
思路二
列出所有字符串用递归求解,对于n个字符串的排列问题,如果能生成n-1个元素的全部排列结果,就能生成n个元素的全部排列结果。接下来我们用Java来实现比较方便。由于java中专门有一个排序集合——TreeSet。又因为题目中要求返回ArrayList类型,故将TreeSet中的元素全部加入到ArrayList中。
import
代码效果图如图所示:
思路三
这种想法是最难想到的,但是代码量以及运行效果确实最优的。留一排他法:留一即将一位留出来,排他即将剩下的进行全排列,然后将留出来的分别拼到全排列串的首位。如abc,留a,排bc得bc、cb,拼:a+bc,a+cb,结果,abc,acb。再留b,排ac……依此类推。具体我们用python将其实现
class
代码效果图如图所示:
总结
本道题主要考察字符串的排序,这里考察的知识点是字符串以及动态规划和递归的相关知识。我们首先想到的思路就是固定一个字母,然后遍历调换其他两个字母,这里有一个小坑就是当字符重复的时候,直接跳过交换。思路二是用到了我们Java中的TreeSet有序集合。大大降低了难度。不过我们题目要求的是返回ArrayList,因此我们还需要将TreeSet集合的元素再放入到ArrayList中。思路三是不好想,但是效果最佳,应用的留一排他法,大大减少了代码量和运行时间。因此,我们在做题的时候,应该多次尝试各种方法,扩展自己的思维,写出优质的代码。总之,我们要继续加油,争取早日找到工作,Good Luck!!!
参考文献
[1]lingongheng
[2]Valonecium