如何使用itertools模块在排序列表中获取下一个按字典顺序排列的较大字符串?

时间:2016-11-09 11:41:05

标签: algorithm python-3.x sorting permutation

我需要输入一个字符串,并返回其下一个按字典顺序排列的字符串。例如,下一个'anmdfg'字符串是'anmdgf'。但是,输入的长度可能非常大,可能包含100个字符或者更多,并且会有一些重复的字符。所以我决定使用itertools.permutations而不将其放入列表中以避免内存过度消耗。

#!/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没有排序。似乎我必须首先生成列表。我尝试过,它耗尽了我的记忆,所以我没有时间终止这个过程。 有没有办法让我在没有列表的情况下对排列结果进行排序?

5 个答案:

答案 0 :(得分:1)

实际上,确实效率低,无法生成低于输出的所有排列。最好使用下面实现的classic linear-time algorithm

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]

答案 1 :(得分:0)

我认为itertools - y的方法是:

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')

请注意,在生成排列之前对start 进行排序,以确保按字典顺序生成排列。

另请注意:

  1. 我一直特别关注我想要捕获的错误,允许任何意外错误发生正确传播(请参阅"The evils of except:");和
  2. 我使用next(thing)而不是thing.__next__()(请参阅What is the relationship between the Python data model and built-in functions?)。

答案 2 :(得分:0)

试试这个,

-lz and -lgdi32

答案 3 :(得分:0)

通用方法是:

  1. 查找字符串的所有排列列表。
  2. 对列表进行排序
  3. 查找商品的索引
  4. 然后获取旁边的项目
  5. 以下是实现该目标的代码:

    >>> 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'
    

答案 4 :(得分:0)

使用python生成下一个排列的相对简单的实现。

    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)