为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Cats萌萌 2021-11-09 20:08:48
我有几个单词(字符串)像'hefg','dhck','dkhc','lmno'通过交换一些或所有字符来转换为新单词,这样新单词在字典上大于原始单词,并且新单词是所有单词中最小的单词大于原始单词单词。例如'dhck' 应该输出'dhkc'而不是'kdhc','dchk'或任何其他。我有这些输入hefgdhckdkhcfedcbabcd哪个应该输出hegfdhkchcdkfedcbabdc我已经尝试过在 python 中使用这段代码,它适用于除'dkhc'和之外的所有内容'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))
查看完整描述

3 回答

?
慕勒3428872

TA贡献1848条经验 获得超6个赞

你可以尝试这样的事情:

  • 以相反的顺序迭代字符串中的字符

  • 跟踪你已经看过的角色,以及你在哪里看到他们

  • 如果您看到比当前字符大的字符,请将其与最小的较大字符交换

  • 对该位置之后的所有字符进行排序以获得最小字符串

示例代码:

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


查看完整回答
反对 回复 2021-11-09
?
千万里不及你

TA贡献1784条经验 获得超9个赞

在一般情况下,最大字符及其位置不会影响算法。例如,对于'fedcbabcd',您可以在字符串的开头添加ana或 az并且不会改变您需要交换最后两个字母的事实。

考虑输入'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'


查看完整回答
反对 回复 2021-11-09
?
慕码人8056858

TA贡献1803条经验 获得超6个赞

我们可以将您的问题改写为查找 string 的下一个字典排列。


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


1) 找出最长的非递增后缀


2)后缀左边的数字是我们的支点


3)在后缀中找到pivot最右边的后继


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


查看完整回答
反对 回复 2021-11-09
  • 3 回答
  • 0 关注
  • 213 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信