剑指offer:输入一个字符串,按字典序打印出该字符串中字符的所有排列。

最近在刷剑指offer的题,刚好这题与网易的一道笔试题颇有渊源,特此记录一下解法。

解法一:最常见的解法莫属固定交换法了(个人理解),固定即先固定一个字母不变,通常固定在子串的首位,如abc固定a,对bc再进行全排列,bc串中固定b,对c进行全排列。交换即在a固定的情况下已经对bc子串进行了全排列之后,那么就将a与第二位的b交换变成bac,此时再回到了固定的步骤,只需固定b,对字串ac进行全排列。依此类推,直至交换完。

特别的需要注意,有重复元素的情况,如aab,那么只需加一个判定条件,当交换的元素相同就无需进行交换,直接跳过即可。千言万语不如上代码。嘿嘿!

class Solution:
    def Permutation(self, ss):
        # write code here
        
        if not ss or not len(ss):
            return ss
        self.res = []
        self.permution(list(ss), 0, len(ss))
        return sorted(self.res)
     
    def permution(self, ss, index, length):
        
        if length-1 == index:
            self.res.append(''.join(ss))
            return
        for i in range(index, length):
            if (ss[i] == ss[index] and i != index):
                continue
            a = ss[i]
            ss[i] = ss[index]
            ss[index] = a
            
            self.permution(ss, index+1, length)
            #前面交换后,此处必须换回来,再进行下一次的固定交换法则
            #要不会有重复的情况(当然你也可以用set或者判断not in 来避免重复)
            a = ss[i]
            ss[i] = ss[index]
            ss[index] = a
        return

解法二:以前看的一位大佬写的代码,颇有韵味。(ps:找不到原链接了,只能冒昧直接贴上代码了。)我简单总结为留一排他法,留一即将一位留出来,排他即将剩下的进行全排列,然后将留出来的分别拼到全排列串的首位。如abc,留a,排bc得bc、cb,拼:a+bc,a+cb,结果,abc,acb。再留b,排ac。。。。。。。依此类推。接着上代码。

class Solution:
    def Permutation(self, ss):
        if len(ss)==0:
            return []
        if len(ss)==1:
            return[ss]
        res=set()
        for i in range(len(ss)):
            for j in self.Permutation(ss[:i]+ss[i+1:]):
                res.add(ss[i]+j)
        return sorted(res)

简短精悍,惊为天人。

你可能感兴趣的:(算法)