How to get the next lexicographically bigger string in a sorted list by using itertools module?
我需要输入一个字符串,并返回它的下一个字典中较大的字符串。例如,下一个字符串"anmdfg"是"anmdgf"。但是,输入的长度可能非常大,可能包含100个字符或更多,并且其中会有一些重复的字符。因此,我决定使用itertools.permutations,而不将其作为AVO的列表。内存消耗过度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #!/usr/bin/env python3 from itertools import permutations a = list(input()) tuple_a = tuple(a) b = permutations(a,len(a)) p = next(b) result = '' try: while 1: p = next(b) if p > tuple_a: result = ''.join(p) print(result) break except: if result == '': print('No answer.') else: if result == '': print('No answer.') |
我的示例中的b没有排序。似乎我必须首先生成列表。我尝试了,但它消耗了我的内存,以至于我没有时间终止进程。我有没有办法在不列清单的情况下对排列结果进行排序?
生成比输出少的所有排列确实非常低效。最好使用下面实现的经典线性时间算法:
1 2 3 4 5 6 | def nextperm(lst): for i in range(len(lst) - 1, 0, -1): if lst[i-1] < lst[i]: for j in range(len(lst) - 1, i-1, -1): if lst[i-1] < lst[j]: return lst[:i-1] + lst[j:j+1] + lst[:j:-1] + lst[i-1:i] + lst[j-1:i-1:-1] |
号
使用python生成下一个排列的实现相对简单。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def nextperm(s): l=[] for i in range(len(s)): l.append(s[i]) for i in range(-1,-len(s),-1): if (l[i] > l[i-1]): break else: pass pos=len(s)+(i-1) for i in range(pos,len(s),1): if (l[pos] > l[i]): (l[pos],l[i-1])=(l[i-1],l[pos]) break else: pass l=l[:pos+1]+l[-1:-(len(s)-pos):-1] s1=''.join(l) return(s1) |
一般方法是:
以下是实现这一目标的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | >>> from itertools import permutations >>> my_string = 'anmdfg' # Permutation of all the strings >>> all_strings = list(permutations(my_string, len(my_string))) # Sorted lexicographically >>> all_string = sorted(all_strings) # index of current string >>> my_index = all_string.index(tuple(my_string)) # Next item (but as tuple) >>> next_value = all_string[my_index+1] >>> next_value ('a', 'n', 'm', 'd', 'g', 'f') # Convert tuple to string >>> ''.join(next_value) 'anmdgf' |
。
试试这个,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | def NextHighestWord(string): S = [ord(i) for i in string] #find non-incresing suffix from last i = len(S) - 1 while i > 0 and S[i-1] >= S[i]: i = i - 1 if i <= 0: return False #next element to highest is pivot j = len(S) - 1 while S[j] <= S[i -1]: j = j - 1 S[i-1],S[j] = S[j],S[i-1] #reverse the suffix S[i:] = S[len(S) - 1 : i-1 : -1] ans = [chr(i) for i in S] ans ="".join(ans) print(ans) return True test = int(input()) for i in range(test): s = input() val = NextHighestWord(s) if val: continue else: print("no answer") |
我认为这样做的方法是:
1 2 3 4 5 6 7 8 9 10 11 12 | from itertools import dropwhile, permutations def next_largest(start): """Return the next largest permutation of the characters in start.""" reference = tuple(start) try: return next(dropwhile( lambda p: p <= reference, permutations(sorted(start)) )) except StopIteration: raise ValueError('No larger string available') |
请注意,在生成排列之前对
还要注意: