字符串的排列
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串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∗(N−1)!=N∗(N−1)∗...∗2∗1
可以得到本题的递归解法。
-
先固定字符串首位,有N种可能。
将N种情况划分为下图两类(a)和(b)。
(a)是自己本身在首位,(b)类是a和剩下的所有元素交换的首位情况。
总而言之,将array[0]和array[0:]两两交换,可以得到N种情况。
-
接下来,考虑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')