牛客网在线编程专题《剑指offer-面试题28》字符串的排列

我的个人微信公众号:Microstrong

微信公众号ID:MicrostrongAI

公众号介绍:Microstrong(小强)同学主要研究机器学习、深度学习、计算机视觉、智能对话系统相关内容,分享在学习过程中的读书笔记!期待您的关注,欢迎一起学习交流进步!

知乎专栏:https://zhuanlan.zhihu.com/Microstrong

Github:https://github.com/Microstrong0305

个人博客:https://blog.csdn.net/program_developer

 题目链接:

https://www.nowcoder.com/practice/fe6b651b66ae47d7acce78ffdd9a96c7?tpId=13&tqId=11180&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目描述:

解题思路:

        如何求出几个字符的所有排列,很多人都不能一下子想出解决方案。那我们是不是可以考虑把这个复杂的问题分解成小的问题呢?比如,我们把一个字符串看成由两部分组成:第一部分为它的第一个字符,第二部分是后面的所有字符。 在图1中, 我们用两种不同的背景颜色区分字符串的两部分。

       我们求整个字符串的排列,可以看成两步:首先求所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换。图1就是分别把第一个字符a和后面的b、c等字符交换的情形。首先固定第一个字符(如图1(a)所示),求后面所有字符的排列。这个时候我们仍把后面的所有字符分成两部分:后面字符的第一个字符,以及这个字符之后的所有字符。然后把第一个字符逐一和它后面的字符交换(如图1(b)所示)...

图1:求字符串的排列的过程

注:(a)把字符串分为两部分,一部分是字符串的第一个字符, 另一部分是第一个字符以后的所有字符(有阴影背景的区域)。 接下来我们求阴影部分的字符串的排列。( b)拿第一个字符和它后面的字符逐个交换。

       分析到这里, 我们就可以看出, 这其实是很典型的递归思路。

已经AC的代码:

(1)第一种递归解法:

class Solution:
 
    #方法一:递归解法
    def __init__(self):
        self.result = []

    def Permutation(self, ss):
       # 判断输入
        if len(ss) == 0:
            return []
        self.PermutationCore(ss, 0)
        sorted(self.result)
        return self.result

    def PermutationCore(self, str, begin):
        # 递归结束的条件:第一位和最后一位交换完成
        if begin == len(str):
            self.result.append(str)
            return

        for i in range(begin, len(str)):
            # 如果字符串相同,则不交换
            if i != begin and str[i] == str[begin]:
                continue

            # 位置交换,Python中字符串的值是不可以修改的,
            # 可以将字符串转换成列表之后修改值,然后用join组成新字符串。
            newStr = list(str)
            temp = newStr[begin]
            newStr[begin] = newStr[i]
            newStr[i] = temp
            str = ''.join(newStr)

            # 递归调用,前面begin + 1的位置不变,后面的字符串全排列
            self.PermutationCore(str, begin + 1)

(2)第二种递归的解法:

 class Solution:

    # 方法二:递归法的第二种写法
    def Permutation2(self, ss):
        if len(ss) <= 0:
            return []
        res = list()
        self.perm(ss, res, '')
        uniq = list(set(res))
        return sorted(uniq)

    def perm(self, ss, res, path):
        if ss == '':
            res.append(path)
        else:
            for i in range(len(ss)):
                self.perm(ss[:i]+ss[i+1:], res, path+ss[i])

(3)第三种递归的解法:

这种解法是在牛客网讨论区看到的,代码看着很简洁,但是理解起来很费劲呀!我是看的迷迷糊糊,还是不太懂,先把代码放这里吧!

class Solution:
 
    # 方法三:递归法的第三种写法
    def Permutation3(self, ss):
        if len(ss) <= 1:
            return ss
        res = set()
        # 遍历字符串,固定第一个元素,第一个元素可以取a,b,c...,然后递归求解
        for i in range(len(ss)):
            for j in self.Permutation3(ss[:i] + ss[i + 1:]):  # 依次固定了元素,其他的全排列(递归求解)
                res.add(ss[i] + j)  # 集合添加元素的方法add(),集合添加去重(若存在重复字符,排列后会存在相同,如baa,baa)
        return sorted(res)  # sorted()能对可迭代对象进行排序,结果返回一个新的list


if __name__ == "__main__":
    sol = Solution()
    str = 'abc'
    print(sol.Permutation3(str))

Reference:

【1】《剑指offer》,何海涛著。

【2】https://cuijiahua.com/blog/2017/12/basis_27.html

【3】https://www.nowcoder.com/questionTerminal/fe6b651b66ae47d7acce78ffdd9a96c7?f=discussion

发布了285 篇原创文章 · 获赞 892 · 访问量 111万+

猜你喜欢

转载自blog.csdn.net/program_developer/article/details/101040667