Tìm tất cả các hoán vị có thể có của một chuỗi đã cho trong python


89

Tôi có một chuỗi. Tôi muốn tạo tất cả các hoán vị từ chuỗi đó, bằng cách thay đổi thứ tự của các ký tự trong đó. Ví dụ, nói:

x='stack'

những gì tôi muốn là một danh sách như thế này,

l=['stack','satck','sackt'.......]

Hiện tại, tôi đang lặp lại trên danh sách ép kiểu của chuỗi, chọn ngẫu nhiên 2 chữ cái và hoán vị chúng để tạo thành một chuỗi mới, và thêm nó vào thiết lập ép kiểu của l. Dựa trên độ dài của chuỗi, tôi đang tính số lần hoán vị có thể và tiếp tục lặp lại cho đến khi kích thước đặt đạt đến giới hạn. Phải có một cách tốt hơn để làm điều này.

Câu trả lời:


143

Mô-đun itertools có một phương thức hữu ích được gọi là hoán vị (). Tài liệu cho biết:

itertools.permutations (có thể lặp lại [, r])

Trả về các hoán vị độ dài r liên tiếp của các phần tử trong có thể lặp lại.

Nếu r không được chỉ định hoặc là Không, thì r mặc định là độ dài của giá trị có thể lặp lại và tất cả các hoán vị có độ dài đầy đủ có thể được tạo ra.

Hoán vị được phát ra theo thứ tự sắp xếp từ vựng. Vì vậy, nếu đầu vào có thể lặp lại được sắp xếp, các bộ hoán vị sẽ được tạo ra theo thứ tự được sắp xếp.

Tuy nhiên, bạn sẽ phải nối các chữ cái đã hoán vị của mình dưới dạng chuỗi.

>>> from itertools import permutations
>>> perms = [''.join(p) for p in permutations('stack')]
>>> perms

['stack', 'stakc', 'stcak', 'stcka', 'stkac', 'stkca', 'satck', 'satkc', 'sactk', 'sackt', 'saktc', 'sakct', ' sctak ',' sctka ',' sck ',' scakt ',' sckta ',' sckat ',' sktac ',' sktca ',' skatc ',' skact ',' skcta ',' skcat ',' tsack ' , 'tsakc', 'tscak', 'tscka', 'tskac', 'tskca', 'tasck', 'taskc', 'tacsk', 'tacks', 'taksc', 'takcs', 'tcsak', ' tcska ',' tcask ',' tcaks ',' tcksa ',' tckas ',' tksac ',' tksca ',' tkasc ',' tkacs ',' tkcsa ',' tkcas ',' astck ','astkc ',' asctk ',' asckt ',' asktc ',' askct ',' atsck ',' atskc ',' atcsk ',' atcks ',' atksc ',' atkcs ',' acstk ',' acskt ' , 'actk', 'actks', 'ackst', 'ackts', 'akstc', 'aksct', 'aktsc', 'aktcs', 'akcst', 'akcts', 'cstak', 'cstka', ' csatk ',' csakt ',' cskta ',' cskat ',' ctsak ',' ctska ',' ctask ',' ctaks ',' ctksa ',' ctkas ',' castk ',' caskt ',' catk ' , 'catks', 'cakst', 'cakts', 'cksta', 'cksat', 'cktsa', 'cktas', 'ckast', 'ckats', 'kstac', 'kstca', 'ksatc','ksact', 'kscta', 'kscat', 'ktsac', 'ktsca', 'ktasc', 'ktacs', 'ktcsa', 'ktcas', 'kastc', 'kasct', 'katsc', 'katcs ',' kacst ',' kacts ',' kcsta ',' kcsat ',' kctsa ',' kctas ',' kcast ',' kcats ']

Nếu bạn thấy mình gặp rắc rối với các bản sao, hãy thử điều chỉnh dữ liệu của bạn thành một cấu trúc không có bản sao như set:

>>> perms = [''.join(p) for p in permutations('stacks')]
>>> len(perms)
720
>>> len(set(perms))
360

Cảm ơn @pst đã chỉ ra rằng đây không phải là những gì chúng ta thường nghĩ về kiểu ép kiểu truyền thống, mà là một lời gọi đến hàm set()tạo.


3
Nit: set(...)không "đúc". Thay vào đó, nó tạo (và cho ra) tập hợp đại diện cho tập hợp đầu vào: một khi được tạo, nó không có liên kết với tập hợp đầu vào (và là một đối tượng khác, không chỉ là một khung nhìn khác).

@pst: Hmm, tôi có xu hướng không đồng ý. Tôi biết trong Ada hoặc Pascal rằng một cast chỉ là một kiểu xem mới trên cùng các bit. Tuy nhiên, ít nhất từ ​​góc độ C, truyền là một thuật ngữ thích hợp cho dù bạn có đang thay đổi cấu trúc cơ bản của dữ liệu hay không. Nó chỉ đơn giản là đề cập đến chuyển đổi kiểu rõ ràng. Xin vui lòng giải thích sự hiểu lầm của tôi nếu bạn có thể.
máy khao khát

1
Đánh máy . Mặc dù, như bạn đã chỉ ra, nó có thể khác với một cái nhìn đơn thuần, tôi muốn cố gắng tách các khái niệm ra để tránh nhầm lẫn. Tôi lẽ ra nên đề cập rõ ràng "cưỡng chế" trong nhận xét đầu tiên của mình, mặc dù tôi chỉ xem xét đặt một hàm: list -> set.

1
Tôi thấy nó, boollà một hàm đánh giá bool (Đúng / Sai) tùy thuộc vào đầu vào. Tôi thấy việc sử dụng các "diễn viên" ở đây là giả mạo và không gây hiểu lầm ...

1
Là một bản cập nhật thú vị, tài liệu đã được thay đổi để nói rằng Hàm tích hợp bool () có thể được sử dụng để chuyển đổi bất kỳ giá trị nào thành Boolean , cụ thể là chuyển đổi thay vì ép kiểu. Điều này xảy ra trong bản phát hành tiếp theo cho cuộc thảo luận này, khiến tôi tin rằng cuộc thảo luận này dẫn đến sự thay đổi trong tài liệu!
máy khao khát

45

Bạn có thể nhận được tất cả N! hoán vị mà không cần nhiều mã

def permutations(string, step = 0):

    # if we've gotten to the end, print the permutation
    if step == len(string):
        print "".join(string)

    # everything to the right of step has not been swapped yet
    for i in range(step, len(string)):

        # copy the string (store as array)
        string_copy = [character for character in string]

        # swap the current index with the step
        string_copy[step], string_copy[i] = string_copy[i], string_copy[step]

        # recurse on the portion of the string that has not been swapped yet (now it's index will begin with step + 1)
        permutations(string_copy, step + 1)

một trong những tốt đẹp. Hoạt động hoàn hảo
kishorer747

1
Tôi chỉ một chút thay đổi nó, chúng ta không cần phải trao đổi các biến nếu tôi == bước
Siraj

4
Thời gian chạy là O (n!) Vì có n! các hoán vị.
Aspen

Tại sao bạn sử dụng step == len(string)thay vì step == len(string) - 1?
tulians

Vì khi đó 2 mục cuối cùng sẽ không bao giờ được hoán đổi. Hãy thử 'abc' cho đến khi b và c được hoán đổi.
Roman Riesen

14

Đây là một cách khác để thực hiện hoán vị chuỗi với mã tối thiểu. Về cơ bản, chúng tôi tạo một vòng lặp và sau đó chúng tôi tiếp tục hoán đổi hai ký tự cùng một lúc, Bên trong vòng lặp, chúng tôi sẽ có đệ quy. Lưu ý, chúng tôi chỉ in khi các chỉ mục đạt đến độ dài của chuỗi của chúng tôi. Ví dụ: ABC i cho điểm bắt đầu của chúng tôi và param đệ quy j cho vòng lặp của chúng tôi

đây là một trợ giúp trực quan về cách nó hoạt động từ trái sang phải từ trên xuống dưới (là thứ tự của hoán vị)

nhập mô tả hình ảnh ở đây

mật mã :

def permute(data, i, length): 
    if i==length: 
        print(''.join(data) )
    else: 
        for j in range(i,length): 
            #swap
            data[i], data[j] = data[j], data[i] 
            permute(data, i+1, length) 
            data[i], data[j] = data[j], data[i]  


string = "ABC"
n = len(string) 
data = list(string) 
permute(data, 0, n)

5
Có thể hữu ích khi đề cập rằng đây là cơ sở của mô hình bactracking .
AruniRC

Thông tin thêm, các mã giống nhau / tương tự: geeksforgeeks.org/… Tôi thích ví dụ của bạn hơn mặc dù với ví dụ đồ họa;)
CTS_AE

8

Người dùng Stack Overflow đã đăng một số giải pháp mạnh nhưng tôi muốn đưa ra một giải pháp khác. Cái này tôi thấy trực quan hơn

Ý tưởng là đối với một chuỗi đã cho: chúng ta có thể đệ quy bằng thuật toán (mã giả):

hoán vị = char + hoán vị (chuỗi - char) cho char trong chuỗi

Tôi hi vọng nó giúp ích cho ai đó!

def permutations(string):
    """
    Create all permutations of a string with non-repeating characters
    """
    permutation_list = []
    if len(string) == 1:
        return [string]
    else:
        for char in string:
            [permutation_list.append(char + a) for a in permutations(string.replace(char, "", 1))]
    return permutation_list

3
Điều này sẽ không hoạt động đối với trường hợp có các ký tự lặp lại (str.replace). Vd: rqqx
sanjay

Sử dụng: [permutation_list.append (char + a) cho một trong hoán vị (String.Replace (char, "", 1))]
user3761855

7

Đây là một hàm đơn giản để trả về các hoán vị duy nhất:

def permutations(string):
    if len(string) == 1:
        return string

    recursive_perms = []
    for c in string:
        for perm in permutations(string.replace(c,'',1)):
            revursive_perms.append(c+perm)

    return set(revursive_perms)

6
1. Bạn mắc lỗi chính tả: revursive_perms-> recursive_perms. 2. Nó sẽ tiết kiệm RAM và thời gian nếu recursive_permslà một tập hợp hơn là một danh sách mà bạn chuyển đổi thành một tập hợp trong câu lệnh trả về. 3. Sẽ hiệu quả hơn nếu sử dụng cắt chuỗi thay vì .replacexây dựng đối số cho lời gọi đệ quy của permutations. 4. Bạn không nên sử dụng stringlàm tên biến vì nó làm mờ tên của stringmô-đun chuẩn .
PM 2Ring

5

Đây là một cách tiếp cận khác với những gì @Adriano và @illerucis đã đăng. Điều này có thời gian chạy tốt hơn, bạn có thể tự kiểm tra bằng cách đo thời gian:

def removeCharFromStr(str, index):
    endIndex = index if index == len(str) else index + 1
    return str[:index] + str[endIndex:]

# 'ab' -> a + 'b', b + 'a'
# 'abc' ->  a + bc, b + ac, c + ab
#           a + cb, b + ca, c + ba
def perm(str):
    if len(str) <= 1:
        return {str}
    permSet = set()
    for i, c in enumerate(str):
        newStr = removeCharFromStr(str, i)
        retSet = perm(newStr)
        for elem in retSet:
            permSet.add(c + elem)
    return permSet

Đối với một chuỗi tùy ý "dadffddxcf", mất 1,1336 giây cho thư viện hoán vị, 9,125 giây cho việc triển khai này và 16,357 giây cho phiên bản của @ Adriano và @illerucis. Tất nhiên bạn vẫn có thể tối ưu hóa nó.


4

itertools.permutationslà tốt, nhưng nó không xử lý tốt với các chuỗi chứa các phần tử lặp lại. Đó là bởi vì bên trong nó hoán vị các chỉ số trình tự và không để ý đến các giá trị của mục trình tự.

Chắc chắn, có thể lọc đầu ra của itertools.permutationsthông qua một tập hợp để loại bỏ các bản sao, nhưng nó vẫn lãng phí thời gian khi tạo các bản sao đó và nếu có một số phần tử lặp lại trong chuỗi cơ sở thì sẽ có rất nhiều bản sao. Ngoài ra, việc sử dụng bộ sưu tập để lưu giữ kết quả sẽ lãng phí RAM, phủ nhận lợi ích của việc sử dụng trình lặp ngay từ đầu.

May mắn thay, có nhiều cách tiếp cận hiệu quả hơn. Đoạn mã dưới đây sử dụng thuật toán của nhà toán học Ấn Độ thế kỷ 14 Narayana Pandita, có thể tìm thấy trong bài viết trên Wikipedia về Phép hoán vị . Thuật toán cổ xưa này vẫn là một trong những cách nhanh nhất được biết đến để tạo các hoán vị theo thứ tự và nó khá mạnh mẽ, ở chỗ nó xử lý đúng các hoán vị có chứa các phần tử lặp lại.

def lexico_permute_string(s):
    ''' Generate all permutations in lexicographic order of string `s`

        This algorithm, due to Narayana Pandita, is from
        https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order

        To produce the next permutation in lexicographic order of sequence `a`

        1. Find the largest index j such that a[j] < a[j + 1]. If no such index exists, 
        the permutation is the last permutation.
        2. Find the largest index k greater than j such that a[j] < a[k].
        3. Swap the value of a[j] with that of a[k].
        4. Reverse the sequence from a[j + 1] up to and including the final element a[n].
    '''

    a = sorted(s)
    n = len(a) - 1
    while True:
        yield ''.join(a)

        #1. Find the largest index j such that a[j] < a[j + 1]
        for j in range(n-1, -1, -1):
            if a[j] < a[j + 1]:
                break
        else:
            return

        #2. Find the largest index k greater than j such that a[j] < a[k]
        v = a[j]
        for k in range(n, j, -1):
            if v < a[k]:
                break

        #3. Swap the value of a[j] with that of a[k].
        a[j], a[k] = a[k], a[j]

        #4. Reverse the tail of the sequence
        a[j+1:] = a[j+1:][::-1]

for s in lexico_permute_string('data'):
    print(s)

đầu ra

aadt
aatd
adat
adta
atad
atda
daat
data
dtaa
taad
tada
tdaa

Tất nhiên, nếu bạn muốn thu thập các chuỗi đã thu được vào một danh sách, bạn có thể làm

list(lexico_permute_string('data'))

hoặc trong các phiên bản Python gần đây:

[*lexico_permute_string('data')]

Giải thích một cách đẹp đẽ.
lmao

2

tại sao bạn không làm đơn giản:

from itertools import permutations
perms = [''.join(p) for p in permutations(['s','t','a','c','k'])]
print perms
print len(perms)
print len(set(perms))

bạn không nhận được bản sao như bạn có thể thấy:

 ['stack', 'stakc', 'stcak', 'stcka', 'stkac', 'stkca', 'satck', 'satkc', 
'sactk', 'sackt', 'saktc', 'sakct', 'sctak', 'sctka', 'scatk', 'scakt', 'sckta',
 'sckat', 'sktac', 'sktca', 'skatc', 'skact', 'skcta', 'skcat', 'tsack', 
'tsakc', 'tscak', 'tscka', 'tskac', 'tskca', 'tasck', 'taskc', 'tacsk', 'tacks', 
'taksc', 'takcs', 'tcsak', 'tcska', 'tcask', 'tcaks', 'tcksa', 'tckas', 'tksac', 
'tksca', 'tkasc', 'tkacs', 'tkcsa', 'tkcas', 'astck', 'astkc', 'asctk', 'asckt', 
'asktc', 'askct', 'atsck', 'atskc', 'atcsk', 'atcks', 'atksc', 'atkcs', 'acstk', 
'acskt', 'actsk', 'actks', 'ackst', 'ackts', 'akstc', 'aksct', 'aktsc', 'aktcs', 
'akcst', 'akcts', 'cstak', 'cstka', 'csatk', 'csakt', 'cskta', 'cskat', 'ctsak', 
'ctska', 'ctask', 'ctaks', 'ctksa', 'ctkas', 'castk', 'caskt', 'catsk', 'catks', 
'cakst', 'cakts', 'cksta', 'cksat', 'cktsa', 'cktas', 'ckast', 'ckats', 'kstac', 
'kstca', 'ksatc', 'ksact', 'kscta', 'kscat', 'ktsac', 'ktsca', 'ktasc', 'ktacs', 
'ktcsa', 'ktcas', 'kastc', 'kasct', 'katsc', 'katcs', 'kacst', 'kacts', 'kcsta', 
'kcsat', 'kctsa', 'kctas', 'kcast', 'kcats']
    120
    120
    [Finished in 0.3s]

4
Không, bạn luôn nhận được các bản sao (hoặc tệ hơn) nếu bạn có hai hoặc nhiều chữ cái giống nhau. Đó là trường hợp trong ví dụ của @ machineyearning, khi anh ấy sử dụng từ ngăn xếp thay vì ngăn xếp . Điều đó có nghĩa là: Giải pháp của bạn chỉ hoạt động đối với các từ có ký tự duy nhất trong đó.
erik

2
def permute(seq):
    if not seq:
        yield seq
    else:
        for i in range(len(seq)):
            rest = seq[:i]+seq[i+1:]
            for x in permute(rest):
                yield seq[i:i+1]+x

print(list(permute('stack')))

2
Bạn có thể giải thích tại sao giải pháp của bạn tốt hơn những giải pháp đã được cung cấp?
Noel Widmer

Tôi không nói rằng giải pháp của tôi tốt hơn những giải pháp khác. Tôi chỉ cung cấp giải pháp của tôi để làm điều đó.
Srivastava


1

Đây là phiên bản cải tiến một chút của mã illerucis để trả về danh sách tất cả các hoán vị của một chuỗi svới các ký tự riêng biệt (không nhất thiết phải theo thứ tự sắp xếp từ vựng) mà không cần sử dụng itertools:

def get_perms(s, i=0):
    """
    Returns a list of all (len(s) - i)! permutations t of s where t[:i] = s[:i].
    """
    # To avoid memory allocations for intermediate strings, use a list of chars.
    if isinstance(s, str):
        s = list(s)

    # Base Case: 0! = 1! = 1.
    # Store the only permutation as an immutable string, not a mutable list.
    if i >= len(s) - 1:
        return ["".join(s)]

    # Inductive Step: (len(s) - i)! = (len(s) - i) * (len(s) - i - 1)!
    # Swap in each suffix character to be at the beginning of the suffix.
    perms = get_perms(s, i + 1)
    for j in range(i + 1, len(s)):
        s[i], s[j] = s[j], s[i]
        perms.extend(get_perms(s, i + 1))
        s[i], s[j] = s[j], s[i]
    return perms

1

Tuy nhiên, một sáng kiến ​​khác và giải pháp đệ quy. Ý tưởng là chọn một chữ cái làm trục và sau đó tạo một từ.

# for a string with length n, there is a factorial n! permutations
alphabet = 'abc'
starting_perm = ''
# with recursion
def premuate(perm, alphabet):
    if not alphabet: # we created one word by using all letters in the alphabet
        print(perm + alphabet)
    else:
        for i in range(len(alphabet)): # iterate over all letters in the alphabet
            premuate(perm + alphabet[i], alphabet[0:i] + alphabet[i+1:]) # chose one letter from the alphabet

# call it            
premuate(starting_perm, alphabet)

Đầu ra:

abc
acb
bac
bca
cab
cba

0

Đây là một phiên bản trình tạo thực sự đơn giản:

def find_all_permutations(s, curr=[]):
    if len(s) == 0:
        yield curr
    else:
        for i, c in enumerate(s):
            for combo in find_all_permutations(s[:i]+s[i+1:], curr + [c]):
                yield "".join(combo)

Tôi nghĩ nó không quá tệ!


0
def f(s):
  if len(s) == 2:
    X = [s, (s[1] + s[0])]
      return X
else:
    list1 = []
    for i in range(0, len(s)):
        Y = f(s[0:i] + s[i+1: len(s)])
        for j in Y:
            list1.append(s[i] + j)
    return list1
s = raw_input()
z = f(s)
print z

xin vui lòng cố gắng thêm một số mô tả.
Arun Vinoth

0
from itertools import permutations
perms = [''.join(p) for p in permutations('ABC')]

perms = [''.join(p) for p in permutations('stack')]

5
xin vui lòng cố gắng thêm một số mô tả.
Arun Vinoth

0
def perm(string):
   res=[]
   for j in range(0,len(string)):
       if(len(string)>1):
           for i in perm(string[1:]):
               res.append(string[0]+i)
       else:
           return [string];
       string=string[1:]+string[0];
   return res;
l=set(perm("abcde"))

Đây là một cách để tạo hoán vị bằng đệ quy, bạn có thể hiểu mã dễ dàng bằng cách lấy chuỗi 'a', 'ab' & 'abc' làm đầu vào.

Bạn nhận được tất cả N! hoán vị với cái này, không có bản sao.


0

Mọi người đều thích mùi mã của riêng mình. Chỉ chia sẻ một cái mà tôi thấy đơn giản nhất:

def get_permutations(word):
    if len(word) == 1:
        yield word

    for i, letter in enumerate(word):
        for perm in get_permutations(word[:i] + word[i+1:]):
            yield letter + perm

0

Chương trình này không loại bỏ các bản sao, nhưng tôi nghĩ rằng đó là một trong những cách tiếp cận hiệu quả nhất:

s=raw_input("Enter a string: ")
print "Permutations :\n",s
size=len(s)
lis=list(range(0,size))
while(True):
    k=-1
    while(k>-size and lis[k-1]>lis[k]):
        k-=1
    if k>-size:
        p=sorted(lis[k-1:])
        e=p[p.index(lis[k-1])+1]
        lis.insert(k-1,'A')
        lis.remove(e)
        lis[lis.index('A')]=e
        lis[k:]=sorted(lis[k:])
        list2=[]
        for k in lis:
                list2.append(s[k])
        print "".join(list2)
    else:
                break

0
def permute_all_chars(list, begin, end):

    if (begin == end):
        print(list)
        return

    for current_position in range(begin, end + 1):
        list[begin], list[current_position] = list[current_position], list[begin]
        permute_all_chars(list, begin + 1, end)
        list[begin], list[current_position] = list[current_position], list[begin]


given_str = 'ABC'
list = []
for char in given_str:
    list.append(char)
permute_all_chars(list, 0, len(list) -1)

xin vui lòng cố gắng thêm một số mô tả.
Arun Vinoth

0

Giải pháp đơn giản hơn bằng cách sử dụng hoán vị.

from itertools import permutations

def stringPermutate(s1):
    length=len(s1)
    if length < 2:
        return s1

    perm = [''.join(p) for p in permutations(s1)]

    return set(perm)

0

Tất cả các từ có thể có với ngăn xếp

from itertools import permutations
for i in permutations('stack'):
    print(''.join(i))
permutations(iterable, r=None)

Trả về các hoán vị độ dài r liên tiếp của các phần tử trong có thể lặp lại.

Nếu r không được chỉ định hoặc là Không, thì r mặc định là độ dài của biến có thể lặp lại và tất cả các hoán vị có độ dài đầy đủ có thể được tạo ra.

Hoán vị được phát ra theo thứ tự sắp xếp từ vựng. Vì vậy, nếu đầu vào có thể lặp lại được sắp xếp, các bộ hoán vị sẽ được tạo ra theo thứ tự được sắp xếp.

Các yếu tố được coi là duy nhất dựa trên vị trí của chúng, không dựa trên giá trị của chúng. Vì vậy, nếu các phần tử đầu vào là duy nhất, sẽ không có giá trị lặp lại trong mỗi hoán vị.


0

Đây là một giải pháp đệ quy n!chấp nhận các phần tử trùng lặp trong chuỗi

import math

def getFactors(root,num):
    sol = []
    # return condition
    if len(num) == 1:
            return [root+num]
    # looping in next iteration
    for i in range(len(num)):  
        # Creating a substring with all remaining char but the taken in this iteration
        if i > 0:
            rem = num[:i]+num[i+1:]
        else:
            rem = num[i+1:]
        # Concatenating existing solutions with the solution of this iteration
        sol = sol + getFactors(root + num[i], rem)
    return sol

Tôi đã xác thực giải pháp có tính đến hai yếu tố, số lượng kết hợp là n!và kết quả không được chứa trùng lặp. Vì thế:

inpt = "1234"
results = getFactors("",inpt)

if len(results) == math.factorial(len(inpt)) | len(results) != len(set(results)):
    print("Wrong approach")
else:
    print("Correct Approach")

-1

Đây là một cách triển khai đệ quy đơn giản và dễ hiểu;

def stringPermutations(s):
    if len(s) < 2:
        yield s
        return
    for pos in range(0, len(s)):
        char = s[pos]
        permForRemaining = list(stringPermutations(s[0:pos] + s[pos+1:]))
        for perm in permForRemaining:
            yield char + perm

1
Bạn nên sửa lỗi thụt đầu dòng. Không cần để lưu các kết quả của cuộc gọi đệ quy để stringPermutationstrong một danh sách - bạn có thể lặp trực tiếp trên nó, ví dụ for perm in stringPermutations(s[:pos] + s[pos+1:]):. Ngoài ra, bạn có thể đơn giản hóa forvòng lặp bằng cách sử dụng enumeratethay vì range, và loại bỏ các char = s[pos]công việc: for pos, char in enumerate(s):.
PM 2Ring

-1

Với đệ quy

# swap ith and jth character of string
def swap(s, i, j):
    q = list(s)
    q[i], q[j] = q[j], q[i]
    return ''.join(q)


# recursive function 
def _permute(p, s, permutes):
    if p >= len(s) - 1:
        permutes.append(s)
        return

    for i in range(p, len(s)):
        _permute(p + 1, swap(s, p, i), permutes)


# helper function
def permute(s):
    permutes = []
    _permute(0, s, permutes)
    return permutes


# TEST IT
s = "1234"
all_permute = permute(s)
print(all_permute)

Với cách tiếp cận Lặp lại (Sử dụng Ngăn xếp)

# swap ith and jth character of string
def swap(s, i, j):
    q = list(s)
    q[i], q[j] = q[j], q[i]
    return ''.join(q)


# iterative function
def permute_using_stack(s):
    stk = [(0, s)]

    permutes = []

    while len(stk) > 0:
        p, s = stk.pop(0)

        if p >= len(s) - 1:
            permutes.append(s)
            continue

        for i in range(p, len(s)):
            stk.append((p + 1, swap(s, p, i)))

    return permutes


# TEST IT
s = "1234"
all_permute = permute_using_stack(s)
print(all_permute)

Được sắp xếp theo ngôn ngữ học

# swap ith and jth character of string
def swap(s, i, j):
    q = list(s)
    q[i], q[j] = q[j], q[i]
    return ''.join(q)


# finds next lexicographic string if exist otherwise returns -1
def next_lexicographical(s):
    for i in range(len(s) - 2, -1, -1):
        if s[i] < s[i + 1]:
            m = s[i + 1]
            swap_pos = i + 1

            for j in range(i + 1, len(s)):
                if m > s[j] > s[i]:
                    m = s[j]
                    swap_pos = j

            if swap_pos != -1:
                s = swap(s, i, swap_pos)
                s = s[:i + 1] + ''.join(sorted(s[i + 1:]))
                return s

    return -1


# helper function
def permute_lexicographically(s):
    s = ''.join(sorted(s))
    permutes = []
    while True:
        permutes.append(s)
        s = next_lexicographical(s)
        if s == -1:
            break
    return permutes


# TEST IT
s = "1234"
all_permute = permute_lexicographically(s)
print(all_permute)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.