簡體   English   中英

字符串操作算法查找大於原始字符串的字符串

[英]String manipulation algorithm to find string greater than original string

我有很少的單詞(字符串),如'hefg','dhck','dkhc','lmno' ,它將通過交換部分或全部字符轉換為新單詞,使新單詞大於原始單詞的字典順序新詞也是比原詞更重要的詞。 例如'dhck'應該輸出'dhkc'而不是'kdhc''dchk'或任何其他。

我有這些輸入

hefg
dhck
dkhc
fedcbabcd

哪個應該輸出

hegf
dhkc
hcdk
fedcbabdc

我在python中試過這個代碼,除了'dkhc''fedcbabcd'之外,它適用於所有人。 我已經發現在'fedcbabcd'情況'fedcbabcd'一個字符是最大的,所以它沒有被交換。我得到"ValueError: min() arg is an empty sequence"

如何修改算法修復案例?

list1=['d','k','h','c']
list2=[]
maxVal=list1.index(max(list1))
for i in range(maxVal):
    temp=list1[maxVal]
    list1[maxVal]=list1[i-1]
    list1[i-1]=temp
    list2.append(''.join(list1))
print(min(list2))

你可以嘗試這樣的事情:

  • 以相反的順序迭代字符串中的字符
  • 跟蹤你已經看過的角色,以及你看到它們的位置
  • 如果你看到的字符比字符大,那就把它換成最小的字符
  • 對該位置后的所有字符進行排序以獲得最小字符串

示例代碼:

def next_word(word):
    word = list(word)
    seen = {}
    for i in range(len(word)-1, -1, -1):
        if any(x > word[i] for x in seen):
            x = min(x for x in seen if x > word[i])
            word[i], word[seen[x]] = word[seen[x]], word[i]
            return ''.join(word[:i+1] + sorted(word[i+1:]))
        if word[i] not in seen:
            seen[word[i]] = i

for word in ["hefg", "dhck", "dkhc", "fedcbabcd"]:
    print(word, next_word(word))

結果:

hefg hegf
dhck dhkc
dkhc hcdk
fedcbabcd fedcbabdc

在一般情況下,最大字符及其位置不會影響算法。 例如,對於'fedcbabcd' ,你可以在字符串的開頭添加a或一個z ,它不會改變你需要交換最后兩個字母的事實。

考慮輸入'dgfecba' 這里的輸出是'eabcdfg' 為什么? 請注意,最后六個字母按遞減順序排序,因此通過更改任何內容,您會按字典順序獲得一個較小的字符串,這是不好的。 因此,您需要替換初始的'd' 我們應該把它放在什么位置? 我們想要比'd'更大的東西,但要盡可能小,所以'e' 剩下的六封信怎么樣? 同樣,我們想要一個盡可能小的字符串,因此我們按字典順序對字母進行排序: 'eabcdfg'

所以算法是:

  • 從字符串的后面開始(右端);
  • 在符號不斷增加時向左走;
  • i成為s[i] < s[i + 1]的最右邊的位置; 在我們的例子中,那是i = 0;
  • 將符號留在位置0,1,..., i - 1不變;
  • 找到i+1 ... n-1包含大於s[i]的最小符號的位置; 叫這個職位j ; 在我們的例子中, j = 3;
  • 交換s[i]s[j] ; 在我們的例子中,我們獲得'egfdcba' ;
  • 反轉字符串s[i+1] ... s[n-1] ; 在我們的例子中,我們獲得'eabcdfg'

您的問題可以重新編寫為查找字符串的下一個字典排列

上述鏈接中的算法描述如下:

1)找到最長的非增加后綴

2)后綴左邊的數字是我們的支點

3)在后綴中找到最右側的樞軸的后繼者

4)交換后繼者和樞軸

5)反轉后綴

上述算法特別有趣,因為它是O(n)

def next_lexicographical(word):
    word = list(word)

    # Find the pivot and the successor
    pivot = next(i for i in range(len(word) - 2, -1, -1) if word[i] < word[i+1])
    successor = next(i for i in range(len(word) - 1, pivot, -1) if word[i] > word[pivot])

    # Swap the pivot and the successor
    word[pivot], word[successor] = word[successor], word[pivot]

    # Reverse the suffix
    word[pivot+1:] = word[-1:pivot:-1]

    # Reform the word and return it
    return ''.join(word)

如果該單詞已經是最后一個詞典排列,則上述算法將引發StopIteration異常。

words = [
    'hefg',
    'dhck',
    'dkhc',
    'fedcbabcd'
]

for word in words:
    print(next_lexicographical(word))

產量

hegf
dhkc
hcdk
fedcbabdc

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM