1. 程式人生 > 程式設計 >python求一個字串的所有排列的實現方法

python求一個字串的所有排列的實現方法

題目描述:

設計一個程式,當輸入一個字串時,要求輸出這個字串的所有排列。
例如輸入字串 abc,要求輸出由字母 a、b、c 所能排列出來的所有字串 abc,acb,bac,bca,cab,cba。

方法:遞迴法

以字串 abc 為例介紹對字串進行全排列的方法。
(1) 首先固定第一個字元 a,然後對後面的兩個字元 b、c 進行全排列;
(2) 交換第一個字元與其後面的字元,即交換 a 與 b,然後對後面的兩個字元 a與c 進行全排列;
(3) 由於第二步交換了 a與b 破壞了字串原來的順序,所以需要再次交換 a與b 使其恢復到原來的順序,然後交換第一個字元與第三個字元(交換a和c),接著固定第一個字元c,對後面的兩個字元 a與b 求全排列。

在對字串求全排列的時候就可以採用遞迴的方式求解。

python求一個字串的所有排列的實現方法

在使用遞迴求解的時候,要注意:
(1) 逐漸縮小問題的規模,並且可以用同樣的方法來求解子問題;
(2) 遞迴一定要有結束條件,否則會導致程式陷入死迴圈;

程式碼實現:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time  : 2020/2/3 9:49
# @Author : buu
# @Software: PyCharm
# @Blog  :https://blog.csdn.net/weixin_44321080
def swap(str,i,j):
  # 交換字元陣列下標為i和j對應的字元
  tmp = str[i]
  str[i] = str[j]
  str[j] = tmp


def permutation(str,start):
  """
  對字串中的字元進行全排列
  :param str: 待排序的字串,list
  :param start: 待排序的子字串的首字元下標
  :return:
  """
  if str == None or start < 0:
    return
  if start == len(str) - 1:
    # 完成全排列後輸出當前排列的字串
    print(''.join(str),end=' ')
  else:
    i = start
    while i < len(str):
      # 交換start與i所在位置的字元
      swap(str,start,i)
      # 固定第一個字元,對剩餘的字元進行全排列
      permutation(str,start + 1)
      # 還原start與i所在位置的字元
      swap(str,i)
      i += 1


def permutation_transe(s):
  str = list(s)
  permutation(str,0)


if __name__ == '__main__':
  s = 'abc'
  permutation_transe(s)

結果:

python求一個字串的所有排列的實現方法

演算法效能分析:
假設這種方法所需的基本運算元為 f(n),f(n) = n×f(n-1) = …= n!
所以時間複雜度為O(n!);
空間複雜度為O(1);

引申:

如何去掉重複的排列?
當字串中沒有重複的字元的時候,它的所有組合對應的字串就沒有重複的情況;當時當字串中有重複的字元的時候,例如 ‘baa',此時如果按照上面介紹的演算法求全排列會有重複的字串。
python求一個字串的所有排列的實現方法

思路:
全排列的主要思路為:從第一個字元起每個字元分別與它們後面的字元進行交換:例如對於“baa”,交換 baa 第一個與第二個字元後得到“aba”,再考慮交換 baa 第一個與第三個字元後得到“aab”,由於 baa 的第二個字元與第三個字元相等,所以會導致兩種交換方式得到的 aba 與 aab 對應的全排列是重複的(在固定aba與aab的第一個字元的情況下,它們對應的全排列都為 aba,aab)。

所以可以知道,去掉重複排列的主要思路為:
從第一個字元起,每個字元分別與它後面的非重複出現的字元進行交換。在遞迴的基礎上只需要增加一個判斷字元是否重複出現的函式即可。

程式碼實現:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time  : 2020/2/3 10:37
# @Author : buu
# @Software: PyCharm
# @Blog  :https://blog.csdn.net/weixin_44321080
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time  : 2020/2/3 9:49
# @Author : buu
# @Software: PyCharm
# @Blog  :https://blog.csdn.net/weixin_44321080
def swap(str,j):
  # 交換字元陣列下標為i和j對應的字元
  tmp = str[i]
  str[i] = str[j]
  str[j] = tmp

def isDuplicate(str,begin,end):
  """
  判斷 [begin,end)區間中是否有字元與 *end相等
  :param begin: 指向字元的指標
  :param end: 指向字元的指標
  :return: 如果有相等的字元True,else False
  """
  i=begin
  while i<end:
    if str[i]==str[end]:
      return True
    else:
      i+=1
  return False


def permutation(str,end=' ')
  else:
    i = start
    while i < len(str):
      # 若有重複字元,則終止當前迴圈,開始下一次迴圈
      if isDuplicate(str,i):
        i+=1
        continue
      # 交換start與i所在位置的字元
      swap(str,0)


if __name__ == '__main__':
  s = 'baa'
  permutation_transe(s)

結果:

python求一個字串的所有排列的實現方法

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。