溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

python求一個字符串的所有排列的實現(xiàn)方法

發(fā)布時間:2020-10-01 05:51:07 來源:腳本之家 閱讀:515 作者:布歐不歐 欄目:開發(fā)技術(shù)

題目描述:

設(shè)計一個程序,當(dāng)輸入一個字符串時,要求輸出這個字符串的所有排列。
例如輸入字符串 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 使其恢復(fù)到原來的順序,然后交換第一個字符與第三個字符(交換a和c),接著固定第一個字符c,對后面的兩個字符 a與b 求全排列。
在對字符串求全排列的時候就可以采用遞歸的方式求解。

python求一個字符串的所有排列的實現(xiàn)方法

在使用遞歸求解的時候,要注意:
(1) 逐漸縮小問題的規(guī)模,并且可以用同樣的方法來求解子問題;
(2) 遞歸一定要有結(jié)束條件,否則會導(dǎo)致程序陷入死循環(huán);

代碼實現(xiàn):

#!/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):
  # 交換字符數(shù)組下標(biāo)為i和j對應(yīng)的字符
  tmp = str[i]
  str[i] = str[j]
  str[j] = tmp


def permutation(str, start):
  """
  對字符串中的字符進行全排列
  :param str: 待排序的字符串,list
  :param start: 待排序的子字符串的首字符下標(biāo)
  :return:
  """
  if str == None or start < 0:
    return
  if start == len(str) - 1:
    # 完成全排列后輸出當(dāng)前排列的字符串
    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, start, i)
      i += 1


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


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

結(jié)果:

python求一個字符串的所有排列的實現(xiàn)方法

算法性能分析:
假設(shè)這種方法所需的基本操作數(shù)為 f(n),f(n) = n×f(n-1) = …= n!
所以時間復(fù)雜度為O(n!);
空間復(fù)雜度為O(1);

引申:

如何去掉重復(fù)的排列?
當(dāng)字符串中沒有重復(fù)的字符的時候,它的所有組合對應(yīng)的字符串就沒有重復(fù)的情況;當(dāng)時當(dāng)字符串中有重復(fù)的字符的時候,例如 ‘baa',此時如果按照上面介紹的算法求全排列會有重復(fù)的字符串。
python求一個字符串的所有排列的實現(xiàn)方法

思路:
全排列的主要思路為:從第一個字符起每個字符分別與它們后面的字符進行交換:例如對于“baa”,交換 baa 第一個與第二個字符后得到“aba”,再考慮交換 baa 第一個與第三個字符后得到“aab”,由于 baa 的第二個字符與第三個字符相等,所以會導(dǎo)致兩種交換方式得到的 aba 與 aab 對應(yīng)的全排列是重復(fù)的(在固定aba與aab的第一個字符的情況下,它們對應(yīng)的全排列都為 aba,aab)。
所以可以知道,去掉重復(fù)排列的主要思路為:
從第一個字符起,每個字符分別與它后面的非重復(fù)出現(xiàn)的字符進行交換。在遞歸的基礎(chǔ)上只需要增加一個判斷字符是否重復(fù)出現(xiàn)的函數(shù)即可。

代碼實現(xiàn):

#!/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, i, j):
  # 交換字符數(shù)組下標(biāo)為i和j對應(yīng)的字符
  tmp = str[i]
  str[i] = str[j]
  str[j] = tmp

def isDuplicate(str,begin,end):
  """
  判斷 [begin,end)區(qū)間中是否有字符與 *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, start):
  """
  對字符串中的字符進行全排列
  :param str: 待排序的字符串,list
  :param start: 待排序的子字符串的首字符下標(biāo)
  :return:
  """
  if str == None or start < 0:
    return
  if start == len(str) - 1:
    # 完成全排列后輸出當(dāng)前排列的字符串
    print(''.join(str),end=' ')
  else:
    i = start
    while i < len(str):
      # 若有重復(fù)字符,則終止當(dāng)前循環(huán),開始下一次循環(huán)
      if isDuplicate(str,start,i):
        i+=1
        continue
      # 交換start與i所在位置的字符
      swap(str, start, i)
      # 固定第一個字符,對剩余的字符進行全排列
      permutation(str, start + 1)
      # 還原start與i所在位置的字符
      swap(str, start, i)
      i += 1


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


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

結(jié)果:

python求一個字符串的所有排列的實現(xiàn)方法

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI