【python数据结构与算法】【剑指offer】字符串的排列

题目描述:

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba,且要求输出字符串按序排列,不可重复

思路:

其实排列问题的思路很简单,有点类似《剑指offer》里那道“青蛙跳台阶”的题目,即——对于字符串长度为n的情况,将第一位的情况固定后,剩下的就是(n-1)长度字符串的情况,也就可以使用递归调用了。

所以很容易想到循环遍历,将遍历到的每个不同的字符放在第一个,然后对删去这个字符的剩余子串进行再次遍历,然后再确定第二个位置的字符,以此类推。最终在字符串被全部确定位置之后,输出“,”作为结束。

因此我们很容易写出以下的代码:

def Permutation(ss):
    if not ss:
        print(',',end='')
    else:
        for i in ss:
            print(i,end='')
            Permutation(ss.replace(i,'',1))   # 删掉该字符串中的第一个"i"字符.注意,后面的1不可省略


Permutation('abc')
>>> abc,cb,bac,ca,cab,ba,

容易看到也容易分析出,有三个字符串漏掉了首字母。这是为什么呢?假设我们首字母是“a”,在递归调用Permutation()时,新的字符串ss='bc'(a被删掉了),则新一轮的for循环会循环到b和c。循环到b的时候,后面继续递归调用输出“c”和“,”,最终输出的就是“abc,”;循环到c的时候,后面继续递归调用输出“b”和“,”,但由于一开始的“a”已经在前面的字符串里了,所有这轮循环其实是没输出“a”的,所以输出结果就是“cb,”。

所以我们应该将每次循环得到的字符立马添加到字符串中去,如首字符若确定为“a”,则立马将“a”加入字符串首个位置,让后面遍历确定的其他字符添加到含有“a”的这个字符串后面。因而我们需要一个空字符串来依次记录加入的字符;

此外,由于最后我们要求输出一个有序的排列,所以我们还涉及到对不同字符串的排序,所以我们还需要一个空list,用于存放每一个排列完毕的字符串。

最后,这个空字符串和空list必须要在递归调用之外,否则每次递归调用都会清空字符串和list,前面的努力就白费了。因此,我们得在Solution类中在定义一个专门用于递归的函数,我姑且称之为per()。

分析完毕,代码见下:

class Solution:
    def Permutation(self, ss):
        if not ss:
            return []
        res = set(self.per([],ss,''))    # 使用set是为了剔除因字符重复而输出的完全一样的排列
        return sorted(res)         

    def per(self,temp,temp_ss,path):     # temp:临时空list;temp_ss:临时空字符串。
        if not temp_ss:
            temp.append(path)
        else:
            for i in temp_ss:
                self.per(temp,temp_ss.replace(i,'',1),path+i)   # replace方法最后的“1”的存在的意义,是防止当字符串中存在重复字符时,以下删了不止一个字符
        return temp

最后说说sort()和sorted()的区别——

  • sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
  • list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。

猜你喜欢

转载自blog.csdn.net/weixin_41712499/article/details/83276043
今日推荐