【python資料結構與演算法】【劍指offer】字串的排列
題目描述:
輸入一個字串,按字典序打印出該字串中字元的所有排列。例如輸入字串abc,則打印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba,且要求輸出字串按序排列,不可重複
思路:
其實排列問題的思路很簡單,有點類似《劍指offer》裡那道“青蛙跳臺階”的題目,即——對於字串長度為n的情況,將第一位的情況固定後,剩下的就是(n-1)長度字串的情況,也就可以使用遞迴呼叫了。
所以很容易想到迴圈遍歷,將遍歷到的每個不同的字元放在第一個,然後對刪去這個字元的剩餘子串進行再次遍歷,然後再確定第二個位置的字元,以此類推。最終在字串被全部確定位置之後,輸出“,”作為結束。
因此我們很容易寫出以下的程式碼:
def Permutation(ss):
if not ss:
print(',',end='')
else:
for i in ss:
print(i,end='')
Permutation(ss.replace(i,'',1)) # 刪掉該字串中的第一個"i"字元.注意,後面的1不可省略
Permutation('abc')
>>> abc,cb,bac,ca,cab,ba,
容易看到也容易分析出,有三個字串漏掉了首字母。這是為什麼呢?假設我們首字母是“a”,在遞迴呼叫Permutation()時,新的字串ss='bc'(a被刪掉了),則新一輪的for迴圈會迴圈到b和c。迴圈到b的時候,後面繼續遞迴呼叫輸出“c”和“,”,最終輸出的就是“abc,
所以我們應該將每次迴圈得到的字元立馬新增到字串中去,如首字元若確定為“a”,則立馬將“a”加入字串首個位置,讓後面遍歷確定的其他字元新增到含有“a”的這個字串後面。因而我們需要一個空字元串來依次記錄加入的字元;
此外,由於最後我們要求輸出一個有序的排列,所以我們還涉及到對不同字串的排序,所以我們還需要一個空list,用於存放每一個排列完畢的字串。
最後,這個空字串和空list必須要在遞迴呼叫之外,否則每次遞迴呼叫都會清空字串和list,前面的努力就白費了。因此,我們得在Solution類中在定義一個專門用於遞迴的函式,我姑且稱之為per()。
分析完畢,程式碼見下:
class Solution:
def Permutation(self, ss):
if not ss:
return []
res = set(self.per([],ss,'')) # 使用set是為了剔除因字元重複而輸出的完全一樣的排列
return sorted(res)
def per(self,temp,temp_ss,path): # temp:臨時空list;temp_ss:臨時空字串。
if not temp_ss:
temp.append(path)
else:
for i in temp_ss:
self.per(temp,temp_ss.replace(i,'',1),path+i) # replace方法最後的“1”的存在的意義,是防止當字串中存在重複字元時,以下刪了不止一個字元
return temp
最後說說sort()和sorted()的區別——
- sort 是應用在 list 上的方法,sorted 可以對所有可迭代的物件進行排序操作。
- list 的 sort 方法返回的是對已經存在的列表進行操作,無返回值,而內建函式 sorted 方法返回的是一個新的 list,而不是在原來的基礎上進行的操作。