[Alg]-字符串的排列

交換法

字典序法

 

字符串全排列:輸入一個字符串,打印出該字符串中字符的所有排列。例如輸入字符串abc,則打印出由字符a,b,c所能排列出來的所有字符串abc,acb,bac,bca,cab和cba。

交換法

把字符串分成兩部分:第一個字符,和剩餘的字符串。因此求字符串的排列,就可以:

  • 可以出現在第一個字符位置的字符:把第一個字符和字符串中剩餘的所有字符交換;
  • 固定第一個字符,遞歸求剩餘字符串的排列。
def getAllRankRecursion(lstOri:list)->set:
    result = set()
    if not lstOri:
        return result

    def addResult(rank):
        get = ''.join(rank)
        result.add(get)
        print(get)

    def needSwap(rank, start, end)->bool:
        for i in range(start,end):
            if rank[i] == rank[end]:
                return False
        return True


    def helper(rank:list, start:int):
        if start==len(rank)-1:
            addResult(rank)
            return       

        helper(rank, start+1)
        for i in range(start+1, len(rank)):
            if(needSwap(rank, start, i)):
                rank[i], rank[start] = rank[start], rank[i]
                helper(rank, start+1)

                rank[i], rank[start] = rank[start], rank[i]

    helper(lstOri, 0)
    return result

注意:在字符串中有重複字符時,需要確定是否需要交換。若字符在前面字符串中已出現過,則不需要交換;即第i個數與第j個數交換時,要求[i,j)中沒有與第j個數相等的數。

字典序法

先對字符串排序(從小到大),然後查找其下一個排列(如"1234"的下一個排列就是"1243"),依次反覆查找,即得到了全排列。如何查找下一個排列(以926520爲例):

  • 從後向前查找第一對相鄰的遞增數:即26;
  • 查找到的一對字符中,前面的字符即爲替換數(對應位置即爲交換點a):即2;
  • 從後面查找比替換數大的最小的數:即5;
  • 交換2與5(即956220),然後將交換點後面的字符串反序(即950226)。
def getAllRankWhile(rank:list)->set:
    def nextPermutation(rank:list)->bool:
        for i in range(len(rank)-1, 0, -1):
            if rank[i-1]<rank[i]:  # get the first Non-increase seq
                changed = i-1
                least = i
                for j in range(i+1, len(rank)):
                    if rank[changed]<rank[j] and rank[least]>=rank[j]:
                        least = j

                # change the elements, and reverse
                rank[changed], rank[least] = rank[least], rank[changed]
                rank[i:] = rank[:i-1:-1]
                return True

        return False

    result = set()
    rank.sort()
    while True:
        get = ''.join(rank)
        print(get)
        result.add(get)

        if not nextPermutation(rank):
            break;

    return result
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章