การค้นหาการเรียงสับเปลี่ยนที่เป็นไปได้ทั้งหมดของสตริงที่กำหนดใน python


93

ฉันมีสตริง ฉันต้องการสร้างการเรียงสับเปลี่ยนทั้งหมดจากสตริงนั้นโดยเปลี่ยนลำดับของอักขระในนั้น ตัวอย่างเช่นพูดว่า:

x='stack'

สิ่งที่ฉันต้องการคือรายการแบบนี้

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

ตอนนี้ฉันกำลังทำซ้ำในรายการของสตริงโดยเลือกตัวอักษร 2 ตัวแบบสุ่มและเปลี่ยนตำแหน่งเพื่อสร้างสตริงใหม่และเพิ่มเพื่อตั้งค่าการแสดง l ตามความยาวของสตริงฉันกำลังคำนวณจำนวนการเรียงสับเปลี่ยนที่เป็นไปได้และทำซ้ำต่อไปจนกว่าขนาดที่ตั้งไว้จะถึงขีด จำกัด ต้องมีวิธีที่ดีกว่านี้

คำตอบ:


148

โมดูล itertools มีวิธีการที่มีประโยชน์ที่เรียกว่าการเรียงสับเปลี่ยน () เอกสารระบุว่า:

itertools.permutations (ทำซ้ำได้ [, r])

ส่งกลับการเรียงลำดับความยาว r ต่อเนื่องขององค์ประกอบในการทำซ้ำ

หากไม่ได้ระบุ r หรือไม่มีดังนั้น r จะดีฟอลต์เป็นความยาวของการวนซ้ำและการเรียงสับเปลี่ยนความยาวเต็มที่เป็นไปได้ทั้งหมดจะถูกสร้างขึ้น

การเรียงลำดับจะแสดงตามลำดับการจัดเรียงศัพท์ ดังนั้นหากมีการจัดเรียงอินพุตที่ทำซ้ำได้สิ่งทอการเรียงสับเปลี่ยนจะถูกจัดเรียงตามลำดับ

คุณจะต้องรวมตัวอักษรดัดแปรของคุณเป็นสตริง

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

หากคุณพบว่าตัวเองมีปัญหากับรายการที่ซ้ำกันให้ลองปรับข้อมูลของคุณให้เป็นโครงสร้างที่ไม่มีข้อมูลซ้ำกันเช่นset:

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

ขอบคุณ @pst ที่ชี้ให้เห็นว่านี่ไม่ใช่สิ่งที่เราคิดว่าเป็นนักแสดงประเภทเดิม แต่เป็นการเรียกร้องให้ผู้set()สร้างมากกว่า


3
Nit: set(...)ไม่ "เหวี่ยง". แต่จะสร้าง (และให้ผล) ชุดที่เป็นตัวแทนของคอลเลกชันอินพุต: เมื่อสร้างแล้วจะไม่มีการเชื่อมโยงกับคอลเล็กชันอินพุต (และเป็นวัตถุอื่นไม่ใช่แค่มุมมองที่แตกต่างกัน)

@pst: อืมฉันมักจะไม่เห็นด้วย ฉันรู้ใน Ada หรือ Pascal ว่านักแสดงเป็นเพียงมุมมองประเภทใหม่ในบิตเดียวกัน อย่างไรก็ตามอย่างน้อยจากมุมมอง C การแคสต์เป็นคำที่เหมาะสมไม่ว่าคุณจะเปลี่ยนโครงสร้างพื้นฐานของข้อมูลหรือไม่ เพียงแค่หมายถึงการแปลงประเภทที่ชัดเจน โปรดอธิบายความเข้าใจผิดของฉันหากคุณสามารถทำได้
เครื่องจักรโหย

1
พิมพ์ดีด . ในขณะที่คุณชี้ให้เห็นอาจแตกต่างจากมุมมองเพียงอย่างเดียวฉันชอบที่จะพยายามแยกแนวคิดออกจากกันเพื่อหลีกเลี่ยงความสับสน ฉันควรพูดถึง "การบีบบังคับ" อย่างชัดเจนในความคิดเห็นแรกของฉันแม้ว่าฉันจะพิจารณาตั้งค่าฟังก์ชัน: list -> set ก็ตาม

1
ฉันดูมันboolเป็นฟังก์ชันที่ประเมินเป็นบูล (True / False) ขึ้นอยู่กับอินพุต ฉันพบว่าการใช้ "แคสต์" ที่นี่เป็นการหลอกลวงและทำให้เข้าใจผิด ...

1
เพื่อเป็นการอัปเดตที่น่าสนใจเอกสารประกอบจึงได้รับการเปลี่ยนแปลงเพื่อบอกว่าฟังก์ชันบูลในตัว () สามารถใช้เพื่อแปลงค่าใด ๆ เป็นบูลีนโดยเฉพาะอย่างยิ่งแปลงแทนการร่าย สิ่งนี้เกิดขึ้นในการเปิดตัวครั้งต่อไปของการสนทนานี้ทำให้ฉันเชื่อว่าการสนทนานี้นำไปสู่การเปลี่ยนแปลงในเอกสาร!
เครื่องจักรโหย

46

คุณจะได้รับ N ทั้งหมด! การเรียงสับเปลี่ยนโดยไม่ต้องใช้รหัสมากนัก

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)

ทำได้ดีนี่. ทำงานได้อย่างสมบูรณ์
kishorer747

1
ฉันเพิ่งแก้ไขเล็กน้อยเราไม่จำเป็นต้องสลับตัวแปรถ้า i == step
work_in_progress

4
รันไทม์คือ O (n!) เนื่องจากมี n! การเรียงสับเปลี่ยน
Aspen

ทำไมคุณถึงใช้step == len(string)แทนstep == len(string) - 1?
ดอกทิวลิป

เพราะงั้น 2 รายการสุดท้ายจะไม่มีการสลับ ลอง 'abc' จนกว่า b และ c จะได้รับการสลับ
Roman Riesen

16

นี่คืออีกวิธีหนึ่งในการเปลี่ยนแปลงสตริงด้วยรหัสขั้นต่ำ โดยพื้นฐานแล้วเราจะสร้างลูปจากนั้นเราจะสลับอักขระสองตัวพร้อมกันภายในลูปเราจะมีการเรียกซ้ำ สังเกตว่าเราจะพิมพ์เฉพาะเมื่อตัวทำดัชนียาวถึงสตริง ตัวอย่าง: ABC i สำหรับจุดเริ่มต้นของเราและพารามิเตอร์การเรียกซ้ำ j สำหรับลูปของเรา

นี่คือภาพความช่วยเหลือวิธีการทำงานจากซ้ายไปขวาบนลงล่าง (คือลำดับของการเปลี่ยนแปลง)

ป้อนคำอธิบายภาพที่นี่

รหัส :

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
อาจเป็นประโยชน์ที่จะกล่าวถึงว่านี่เป็นพื้นฐานของกระบวนทัศน์แบบbactracking
AruniRC

ข้อมูลเพิ่มเติมรหัสเดียวกัน / คล้ายกัน: geeksforgeeks.org/…ฉันชอบตัวอย่างของคุณดีกว่า แต่มีตัวอย่างกราฟิก;)
CTS_AE

8

ผู้ใช้ Stack Overflow ได้โพสต์โซลูชันที่แข็งแกร่งไปแล้ว แต่ฉันต้องการแสดงวิธีแก้ปัญหาอื่น อันนี้ฉันพบว่าใช้งานง่ายกว่า

แนวคิดก็คือสำหรับสตริงที่กำหนด: เราสามารถเรียกคืนโดยอัลกอริทึม (รหัสหลอก):

วิธีการเรียงสับเปลี่ยน = char + การเรียงสับเปลี่ยน (สตริง - ถ่าน) สำหรับอักขระในสตริง

ฉันหวังว่ามันจะช่วยใครสักคน!

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

4
สิ่งนี้จะใช้ไม่ได้กับกรณีที่มีอักขระซ้ำกัน (str.replace) เช่น: rqqx
sanjay

ใช้: [permutation_list.append (char + a) สำหรับการเรียงสับเปลี่ยน (string.replace (char, "", 1))]
user3761855

7

นี่คือฟังก์ชันง่ายๆในการคืนค่าการเรียงสับเปลี่ยนที่ไม่ซ้ำกัน:

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. คุณมีการพิมพ์ผิด: ->revursive_perms recursive_perms2. จะช่วยประหยัด RAM และเวลาหากrecursive_permsเป็นชุดแทนที่จะเป็นรายการที่คุณแปลงเป็นชุดในคำสั่ง return 3 มันจะมีประสิทธิภาพมากขึ้นเพื่อใช้สตริงหั่นแทนการ.replaceที่จะสร้างหาเรื่องไปยังโทร recursive permutationsของ 4. ไม่ควรใช้stringเป็นชื่อตัวแปรเพราะจะทำให้ชื่อของstringโมดูลมาตรฐานเป็นเงา
PM 2Ring

5

นี่เป็นอีกแนวทางหนึ่งที่แตกต่างจากที่ @Adriano และ @illerucis โพสต์ไว้ สิ่งนี้มีรันไทม์ที่ดีกว่าคุณสามารถตรวจสอบตัวเองได้โดยการวัดเวลา:

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

สำหรับสตริงที่กำหนดเอง "dadffddxcf" ใช้เวลา 1.1336 วินาทีสำหรับไลบรารีการเปลี่ยนแปลง 9.125 วินาทีสำหรับการนำไปใช้งานและ 16.357 วินาทีสำหรับเวอร์ชันของ @ Adriano และ @illerucis แน่นอนว่าคุณยังสามารถเพิ่มประสิทธิภาพได้


4

itertools.permutationsเป็นสิ่งที่ดี แต่ไม่ได้จัดการกับลำดับที่มีองค์ประกอบซ้ำ ๆ นั่นเป็นเพราะภายในอนุญาตดัชนีลำดับและไม่สนใจค่ารายการลำดับ

แน่นอนว่าเป็นไปได้ที่จะกรองผลลัพธ์ของitertools.permutationsชุดเพื่อกำจัดรายการที่ซ้ำกัน แต่ก็ยังเสียเวลาในการสร้างรายการที่ซ้ำกันและหากมีองค์ประกอบที่ซ้ำกันหลายรายการในลำดับฐานจะมีรายการที่ซ้ำกันจำนวนมาก นอกจากนี้การใช้คอลเลกชันเพื่อเก็บผลลัพธ์จะทำให้สิ้นเปลือง RAM โดยไม่คำนึงถึงประโยชน์ของการใช้ตัววนซ้ำในตอนแรก

โชคดีที่มีแนวทางที่มีประสิทธิภาพมากกว่านี้ รหัสด้านล่างใช้อัลกอริทึมของศตวรรษที่ 14 อินเดียคณิตศาสตร์นารายณ์ Pandita ซึ่งสามารถพบได้ในบทความวิกิพีเดียเรียงสับเปลี่ยน อัลกอริทึมโบราณนี้ยังคงเป็นหนึ่งในวิธีที่รู้จักกันเร็วที่สุดในการสร้างการเรียงสับเปลี่ยนตามลำดับและค่อนข้างมีประสิทธิภาพในการจัดการการเรียงสับเปลี่ยนที่มีองค์ประกอบซ้ำ ๆ อย่างเหมาะสม

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)

เอาท์พุท

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

แน่นอนว่าหากคุณต้องการรวบรวมสตริงที่ให้ผลเป็นรายการคุณสามารถทำได้

list(lexico_permute_string('data'))

หรือใน Python เวอร์ชันล่าสุด:

[*lexico_permute_string('data')]

อธิบายอย่างสวยงาม
lmao

2

ทำไมคุณไม่ทำง่ายๆ:

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

คุณจะไม่ซ้ำกันอย่างที่คุณเห็น:

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

5
ไม่คุณจะได้รับข้อมูลซ้ำเสมอ (หรือแย่กว่านั้น) หากคุณมีตัวอักษรเดียวกันสองตัวขึ้นไป นั่นคือกรณีในตัวอย่าง @ machineyearning ของในขณะที่เขาใช้คำว่ากองแทนสแต็ค นั่นหมายความว่า: โซลูชันของคุณใช้ได้กับคำที่มีอักขระเฉพาะเท่านั้น
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
คุณช่วยอธิบายได้ไหมว่าทำไมโซลูชันของคุณถึงดีกว่าที่ให้มาแล้ว?
Noel Widmer

ฉันไม่ได้บอกว่าทางออกของฉันดีกว่าคนอื่น ๆ ฉันเพิ่งให้วิธีแก้ปัญหาของฉันเพื่อทำเช่นนั้น
Srivastava

1

4
ชุดค่าผสมไม่เกี่ยวข้องกับปัญหาของเขา เขากำลังขนย้ายตัวอักษรซึ่งหมายความว่าคำสั่งมีความเกี่ยวข้องซึ่งหมายถึงเฉพาะการเรียงสับเปลี่ยน
เครื่องจักรโหยหา

1

ต่อไปนี้เป็นรุ่นที่ดีขึ้นเล็กน้อยของillerucisรหัส 's เพื่อการกลับรายการพีชคณิตทั้งหมดของสตริงsที่มีตัวอักษรที่แตกต่างกัน (ไม่จำเป็นต้องอยู่ในลำดับการจัดเรียงพจนานุกรม) โดยไม่ต้องใช้ 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

อีกหนึ่งความคิดริเริ่มและการแก้ปัญหาซ้ำ แนวคิดคือการเลือกตัวอักษรเป็นเดือยแล้วสร้างคำ

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

เอาท์พุต:

abc
acb
bac
bca
cab
cba

0

นี่เป็นเวอร์ชันเครื่องกำเนิดไฟฟ้าที่เรียบง่ายจริงๆ:

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)

คิดว่าไม่เลวร้ายเท่าไหร่!


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

โปรดลองเพิ่มคำอธิบาย
Arun Vinoth

0

นี่คือการนำไปใช้ซ้ำที่ง่ายและตรงไปตรงมา

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
คุณควรแก้ไขการเยื้อง ไม่มีความจำเป็นที่จะบันทึกผลของการโทร recursive ที่จะเป็นstringPermutationsในรายการ - for perm in stringPermutations(s[:pos] + s[pos+1:]):คุณสามารถย้ำโดยตรงมากกว่านั้นเช่น นอกจากนี้คุณสามารถลดความซับซ้อนของforวงโดยใช้enumerateแทนrangeและกำจัดที่ได้รับมอบหมาย:char = s[pos] for pos, char in enumerate(s):
PM 2Ring


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

นี่เป็นวิธีหนึ่งในการสร้างการเรียงสับเปลี่ยนด้วยการเรียกซ้ำคุณสามารถเข้าใจรหัสได้อย่างง่ายดายโดยใช้สตริง 'a', 'ab' & 'abc' เป็นอินพุต

คุณจะได้รับ N ทั้งหมด! การเรียงสับเปลี่ยนกับสิ่งนี้โดยไม่ซ้ำกัน


0

ทุกคนชอบกลิ่นของรหัสของตัวเอง แค่แบ่งปันสิ่งที่ฉันคิดว่าง่ายที่สุด:

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

โปรแกรมนี้ไม่ได้กำจัดรายการที่ซ้ำกัน แต่ฉันคิดว่ามันเป็นวิธีที่มีประสิทธิภาพที่สุดวิธีหนึ่ง:

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)

โปรดลองเพิ่มคำอธิบาย
Arun Vinoth

0

วิธีแก้ปัญหาที่ง่ายกว่าโดยใช้การเรียงสับเปลี่ยน

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

Word ที่เป็นไปได้ทั้งหมดพร้อมสแต็ก

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

ส่งกลับการเรียงลำดับความยาว r ต่อเนื่องขององค์ประกอบในการทำซ้ำ

หากไม่ได้ระบุ r หรือไม่มีดังนั้น r จะดีฟอลต์เป็นความยาวของการวนซ้ำและการเรียงสับเปลี่ยนความยาวเต็มที่เป็นไปได้ทั้งหมดจะถูกสร้างขึ้น

การเรียงลำดับจะแสดงตามลำดับการจัดเรียงศัพท์ ดังนั้นหากมีการจัดเรียงอินพุตที่ทำซ้ำได้สิ่งทอการเรียงสับเปลี่ยนจะถูกจัดเรียงตามลำดับ

องค์ประกอบจะถือว่าไม่ซ้ำกันตามตำแหน่งไม่ใช่ตามมูลค่า ดังนั้นหากองค์ประกอบอินพุตไม่ซ้ำกันจะไม่มีค่าซ้ำในแต่ละการเรียงสับเปลี่ยน


0

นี่คือโซลูชันแบบวนซ้ำn!ซึ่งยอมรับองค์ประกอบที่ซ้ำกันในสตริง

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

ฉันตรวจสอบความถูกต้องของโซลูชันโดยคำนึงถึงสององค์ประกอบจำนวนชุดค่าผสมคือn!และผลลัพธ์ต้องไม่มีรายการที่ซ้ำกัน ดังนั้น:

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

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

0

ด้วยวิธีการเรียกซ้ำ

def permute(word):
    if len(word) == 1:
        return [word]
    permutations = permute(word[1:])
    character = word[0]
    result = []
    for p in permutations:
        for i in range(len(p)+1):
            result.append(p[:i] + character + p[i:])
    return result




running code.

>>> permute('abc')
['abc', 'bac', 'bca', 'acb', 'cab', 'cba']

-1

ด้วยการเรียกซ้ำ

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

ด้วยวิธีการทำซ้ำ (การใช้ Stack)

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

ด้วยการจัดเรียงตามศัพท์

# 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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.