博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(python版)《剑指Offer》JZ27:字符串的排列
阅读量:4090 次
发布时间:2019-05-25

本文共 4040 字,大约阅读时间需要 13 分钟。

在这里插入图片描述

【思路1】回溯法

  1. 终止条件: 当 x = len( c )−1 时,代表所有位已固定(最后一位只有 1 种情况),则将当前组合 c 转化为字符串并加入 res,并返回;
  2. 递推参数: 当前固定位 x ;
  3. 递推工作: 初始化一个 Set ,用于排除重复的字符;将第 x 位字符与 i∈[x, len( c )] 字符分别交换,并进入下层递归;
    1. 剪枝: 若 c[i] 在 Set​ 中,代表其是重复字符,因此“剪枝”;
    2. 将 c[i] 加入 Set​ ,以便之后遇到重复字符时剪枝;
    3. 固定字符: 将字符 c[i] 和 c[x] 交换,即固定 c[i] 为当前位字符;
    4. 开启下层递归: 调用 dfs(x+1) ,即开始固定第 (x + 1) 个字符;
    5. 还原交换: 将字符 c[i] 和 c[x] 交换(还原之前的交换);
class Solution:    def permutation(self, s: str) -> List[str]:        c, res = list(s), []        def dfs(x):            if x == len(c) - 1:                res.append(''.join(c)) # 添加排列方案                return            dic = set()            for i in range(x, len(c)):                if c[i] in dic: continue # 重复,因此剪枝                dic.add(c[i])                c[i], c[x] = c[x], c[i] # 交换,将 c[i] 固定在第 x 位                dfs(x + 1) # 开启固定第 x + 1 位字符                c[i], c[x] = c[x], c[i] # 恢复交换        dfs(0)        return res'''作者:jyd链接:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/solution/mian-shi-ti-38-zi-fu-chuan-de-pai-lie-hui-su-fa-by/来源:力扣(LeetCode)'''
  • 时间复杂度 O(N!) : N 为字符串 s 的长度;时间复杂度和字符串排列的方案数成线性关系,方案数为 N×(N−1)×(N−2)…×2×1 ,因此复杂度为 O(N!) 。
  • 空间复杂度 O(N2) : 全排列的递归深度为 N ,系统累计使用栈空间大小为 O(N) ;递归中辅助 Set 累计存储的字符数量最多为 N + (N-1) + … + 2 + 1 = (N+1)N/2 ,即占用 O(N2)的额外空间。

在这里插入图片描述

在这里插入图片描述

【思路2】回溯+回溯

ss:待处理的序列

res:已存入的序列
ans:存放已排序好的字符串

class Solution(object):    def permutation(self, s):        s_list = list(s)        ans = set()        def dfs(ss, res=[]):            if len(ss) == 0:                ans.add("".join(res))                return            for i in range(len(ss)):                dfs(ss[:i]+ss[i+1:], res+[ss[i]])        dfs(s_list, [])        return list(ans)'''作者:fei-ben-de-cai-zhu-UC4q0zhusJ链接:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/solution/pythonhui-su-fa-setjie-ti-by-fei-ben-de-cai-zhu-uc/来源:力扣(LeetCode)'''

在这里插入图片描述

递归的另一种写法
快一点

class Solution:    def permutation(self, s: str) -> List[str]:        if len(s) <=0:            return []        res = list()        self.perm(s,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])

【附】打印版

–思路1–

class Solution:    def permutation(self, s):        c, res = list(s), []        def dfs(x):            # print('固定 x=',x)            if x == len(c) - 1:                print('最后一个字符x =',c[x])                print('排序好的c=',c)                res.append(''.join(c)) # 添加排列方案 遇到终止条件时,才添加最后一个元素                print('此时res=',res)                print()                return            dic = set()            for i in range(x, len(c)):                if c[i] in dic: continue # 重复,因此剪枝                dic.add(c[i])                print('当前字符c[x] =',c[x],end='\t\t')                print('c[%d]=%s'%(i,c[i]),end='\t')                print('i还可取:',[i for i in range(x+1,len(c))])                print('待排序的dic =',dic)                                c[i], c[x] = c[x], c[i] # 交换,将 c[i] 固定在第 x 位                print('# 交换后c =',c)                print('开始c[x+1]=c[%d]=%s的回溯:'%((x+1),c[x+1]))                dfs(x + 1) # 开启固定第 x + 1 位字符                # print('添加后 dic=',dic)                c[i], c[x] = c[x], c[i] # 恢复交换                print('恢复交换c =',c)                print('==='*10)        dfs(0)        return resif __name__ == "__main__":    s = "abc"    print(Solution().permutation(s))

–思路2–

class Solution2(object):    def permutation(self, s):        s_list = list(s)        ans = set()        def dfs(ss, res=[]):            if len(ss) == 0:                ans.add("".join(res))                print('ans=',ans)                print('结束一轮')                return            for i in range(len(ss)):                print('ss=',ss,end='\t')                print('res=',res)                print(ss[:i]+ss[i+1:],res+[ss[i]])                dfs(ss[:i]+ss[i+1:], res+[ss[i]])        dfs(s_list, [])        print(ans)        return list(ans)if __name__ == "__main__":    s = "abc"    print(Solution().permutation(s))

转载地址:http://bfjii.baihongyu.com/

你可能感兴趣的文章
一个很棒的Flutter学习资源列表
查看>>
为什么你应该放弃React老的Context API用新的Context API
查看>>
Flutter 布局控件完结篇
查看>>
Koa2初体验
查看>>
Koa 2 初体验(二)
查看>>
Koa2框架原理解析和实现
查看>>
vue源码系列文章good
查看>>
你不知道的Virtual DOM
查看>>
VUE面试题总结
查看>>
写好JavaScript条件语句的5条守则
查看>>
原生JS中DOM节点相关API合集
查看>>
【TINY4412】U-BOOT移植笔记:(7)SDRAM驱动
查看>>
【TINY4412】U-BOOT移植笔记:(12)BEEP驱动
查看>>
单链表的修改和删除
查看>>
C++的三个基本特征:封装、继承、多态
查看>>
C++虚函数的总结
查看>>
什么是URL地址?
查看>>
C++多态的实现方式总结
查看>>
学习C++需要注意的问题
查看>>
C++模板
查看>>