字符串的排列

字符串的排列

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

思路

  • 解法一
    集合和队列。
    首先,给定字符串,求字符串的全排列,那么结果集的元素个数就确定了。
    g o a l = l e n ( s t r ) ! goal = len(str)! goal=len(str)!
    其次,来分析字符串的全排列。
    字符串“abc”,结果集“abc,bac,cba,acb,cab,bca”,可以划分为如下两个部分。
    左边,abc,任意两个元素两两交换,加上本身,可以得到四种组合方式。
    右边,剩下来的两种“cab,bca”可以看成bac交换两个元素得到的。
    在这里插入图片描述
    因此,我们可以将abc两两交换后的结果弹出,继续进行两两交换,直到结果集中的个数满足goal。循环终止。
    在这里插入图片描述
  • 解法二
    递归和全排列公式。
    根据全排列公式,假设字符串长度为N:
    g o a l = N ! = N ∗ ( N − 1 ) ! = N ∗ ( N − 1 ) ∗ . . . ∗ 2 ∗ 1 goal = N! =N*(N-1)!=N*(N-1)*...*2*1 goal=N!=N(N1)!=N(N1)...21
    可以得到本题的递归解法。
  1. 先固定字符串首位,有N种可能。
    将N种情况划分为下图两类(a)和(b)。
    (a)是自己本身在首位,(b)类是a和剩下的所有元素交换的首位情况。
    总而言之,将array[0]和array[0:]两两交换,可以得到N种情况。
    在这里插入图片描述

  2. 接下来,考虑array[1],与此类此,将array[1]和array[1:]两两交换,可以得到N-1种可能。
    3.最后,到达最后一个下标位置时,返回结果。
    在这里插入图片描述

  • 算法比较
    第一种方法无法处理字符串中有重复字符的情况。

代码

  • 解法一
# -*- coding:utf-8 -*-
import collections

class Solution:
    def Swap(self,taskStr):
        resultList = []
        taskList = list(taskStr)
        for start in range(len(taskStr)-1):
            for end in range(1,len(taskStr)):
                taskList[start],taskList[end] = taskList[end],taskList[start]
                changeStr = ''.join(taskList)
                if  changeStr not in resSet:
                    resSet.add(changeStr)
                    resultList.append(changeStr)
        return resultList

    def Permutation(self, ss):
        """全排列版本"""
        goal = reduce(lambda x,y:x*y,range(1,len(ss)+1))
        q = collections.deque()
        q.appendleft(ss)
        global resSet
        resSet = set()
        resSet.add(ss)

        while len(resSet) != goal:
            taskStr = q.pop()
            resultList = self.Swap(taskStr)
            for result in resultList:
                q.appendleft(result)
        resList = []
        while resSet:
            resList.append(resSet.pop())
        resList.sort()
        print resList
    
if __name__ == "__main__":
    Solution().Permutation('acb')
  • 解法二
# -*- coding: utf-8 -*-
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,ss,begin):
        if begin == len(ss)-1:
            self.result.append(ss)
            return
        for i in range(begin,len(ss)):
            if i != begin and ss[i] == ss[begin]:                #特殊情况:字符串中包含重复值
                continue
            ssList = list(ss)
            ssList[i],ssList[begin] = ssList[begin],ssList[i]    #将当前下标begin对应元素和ss[begin:]所有元素两两交换,包含自身
            ss = ''.join(ssList)
            self.PermutationCore(ss,begin+1)                     #begin位置交换完成后,考虑begin+1位置. 

if __name__ == "__main__":
    print Solution().Permutation('aa')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值