รายการการเรียงสับเปลี่ยนทั้งหมดของสตริง / จำนวนเต็ม


159

งานทั่วไปในการสัมภาษณ์การเขียนโปรแกรม (ไม่ใช่จากประสบการณ์การสัมภาษณ์ของฉัน) คือการใช้สตริงหรือจำนวนเต็มและรายการการเปลี่ยนแปลงที่เป็นไปได้ทั้งหมด

มีตัวอย่างของวิธีการทำเช่นนี้และตรรกะที่อยู่เบื้องหลังการแก้ปัญหาดังกล่าวหรือไม่?

ฉันเห็นตัวอย่างโค้ดบางส่วน แต่พวกเขาไม่ได้แสดงความคิดเห็น / อธิบายอย่างดีและยากที่จะติดตาม


1
นี่คือคำถามของพีชคณิตที่มีคำตอบที่ดีซึ่งรวมถึงกราฟแต่ไม่ใช่ใน C #
ไม่ทราบผู้ใช้

คำตอบ:


152

ก่อนอื่นเลย: มันมีกลิ่นเหมือนการวนซ้ำแน่นอน!

เมื่อคุณต้องการทราบหลักการฉันก็พยายามทำให้ดีที่สุดเพื่ออธิบายภาษามนุษย์ ฉันคิดว่าการเรียกซ้ำเป็นเรื่องง่ายมากส่วนใหญ่ คุณต้องเข้าใจสองขั้นตอน:

  1. ขั้นตอนแรก
  2. ขั้นตอนอื่น ๆ ทั้งหมด (ทั้งหมดด้วยตรรกะเดียวกัน)

ในภาษามนุษย์ :

ในระยะสั้น:
1 การเปลี่ยนแปลงของ 1 องค์ประกอบเป็นองค์ประกอบหนึ่ง
2. การเรียงสับเปลี่ยนของชุดขององค์ประกอบคือรายการแต่ละองค์ประกอบเชื่อมต่อกับการเปลี่ยนแปลงขององค์ประกอบอื่น ๆ

ตัวอย่าง:

หากเซ็ตนั้นมีองค์ประกอบเดียว ->
คืนมัน
ใบอนุญาต (a) -> a

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

ใบอนุญาต (ab) ->

a + perm (b) -> ab

b + perm (a) -> ba

เพิ่มเติม: สำหรับตัวละครแต่ละตัวในชุด: คืนตัวอักษร, ตัดแบ่งด้วย perumation> ส่วนที่เหลือของชุด

ใบอนุญาต (abc) ->

a + perm (bc) -> abc , acb

b + perm (ac) -> bac , bca

c + perm (ab) -> cab , cba

ใบอนุญาต (abc ... z) ->

a + ดัด (... ), b + ดัด (.... )
....

ฉันพบpseudocodeบนhttp://www.programmersheaven.com/mb/Algorithms/369713/369713/permutation-algorithm-help/ :

makePermutations(permutation) {
  if (length permutation < required length) {
    for (i = min digit to max digit) {
      if (i not in permutation) {
        makePermutations(permutation+i)
      }
    }
  }
  else {
    add permutation to list
  }
}

ค#

ตกลงและมีบางสิ่งที่ซับซ้อนยิ่งขึ้น (และเนื่องจากมีการติดแท็ก c #) จากhttp://radio.weblogs.com/0111551/stories/2002/10/14/permutations.html : ค่อนข้างยาว แต่ฉันตัดสินใจที่จะคัดลอก อย่างไรก็ตามโพสต์จึงไม่ขึ้นอยู่กับต้นฉบับ

ฟังก์ชั่นใช้สตริงของตัวอักษรและเขียนการเรียงสับเปลี่ยนที่เป็นไปได้ของสตริงที่แน่นอนดังนั้นตัวอย่างเช่นหากมีการจัดหา "ABC" ควรล้นออก:

ABC, ACB, BAC, BCA, CAB, CBA

รหัส:

class Program
{
    private static void Swap(ref char a, ref char b)
    {
        if (a == b) return;

        var temp = a;
        a = b;
        b = temp;
    }

    public static void GetPer(char[] list)
    {
        int x = list.Length - 1;
        GetPer(list, 0, x);
    }

    private static void GetPer(char[] list, int k, int m)
    {
        if (k == m)
        {
            Console.Write(list);
        }
        else
            for (int i = k; i <= m; i++)
            {
                   Swap(ref list[k], ref list[i]);
                   GetPer(list, k + 1, m);
                   Swap(ref list[k], ref list[i]);
            }
    }

    static void Main()
    {
        string str = "sagiv";
        char[] arr = str.ToCharArray();
        GetPer(arr);
    }
}

21
เพื่อความชัดเจนมากขึ้นฉันจะเรียก k "recursionDepth" และเรียก m "maxDepth"
Nerf Herder

3
สลับที่ 2 ( Swap(ref list[k], ref list[i]);) ไม่จำเป็น
dance2die

1
ขอบคุณสำหรับการแก้ปัญหานี้ ฉันสร้างซอนี้ ( dotnetfiddle.net/oTzihw ) จากมัน (ด้วยการตั้งชื่อที่เหมาะสมแทน k และ m) เท่าที่ฉันเข้าใจอัลโกจำเป็นต้องสลับที่สอง (เพื่อย้อนกลับ) เนื่องจากคุณแก้ไขอาเรย์ดั้งเดิมในตำแหน่ง
Andrew

3
จุดเล็ก ๆ : ดูเหมือนว่าวิธีการแลกเปลี่ยนจะดีกว่าที่จะดำเนินการกับตัวแปรบัฟเฟอร์ชั่วคราวและไม่ได้ใช้ XORs ( dotnetperls.com/swap )
Sergioet

7
ด้วยการใช้ Tuples C # 7 คุณสามารถทำให้การแลกเปลี่ยนนั้นดูมีความสง่างามมากขึ้น:(a[x], a[y]) = (a[y], a[x]);
Darren

81

มันเป็นเพียงสองบรรทัดของรหัสหากอนุญาตให้ใช้ LINQ โปรดดูคำตอบของฉันที่นี่

แก้ไข

นี่คือฟังก์ชั่นทั่วไปของฉันซึ่งสามารถคืนค่าพีชคณิตทั้งหมด (ไม่ใช่ชุดค่าผสม) จากรายการ T:

static IEnumerable<IEnumerable<T>>
    GetPermutations<T>(IEnumerable<T> list, int length)
{
    if (length == 1) return list.Select(t => new T[] { t });

    return GetPermutations(list, length - 1)
        .SelectMany(t => list.Where(e => !t.Contains(e)),
            (t1, t2) => t1.Concat(new T[] { t2 }));
}

ตัวอย่าง:

IEnumerable<IEnumerable<int>> result =
    GetPermutations(Enumerable.Range(1, 3), 3);

เอาท์พุท - รายการของรายการจำนวนเต็ม:

{1,2,3} {1,3,2} {2,1,3} {2,3,1} {3,1,2} {3,2,1}

เนื่องจากฟังก์ชันนี้ใช้ LINQ ดังนั้นจึงต้องใช้. net 3.5 ขึ้นไป


3
ชุดค่าผสมและวิธีเรียงสับเปลี่ยนเป็นสิ่งที่แตกต่างกัน มันคล้ายกัน แต่คำตอบของคุณดูเหมือนจะตอบปัญหาที่แตกต่างจากการเรียงสับเปลี่ยนของชุดองค์ประกอบ
Shawn Kovac

@ ShawnKovac ขอบคุณที่ชี้นำสิ่งนี้! ฉันได้อัปเดตโค้ดของฉันจากชุดค่าผสมเป็นการเปลี่ยนแปลง
Pengyang

1
@Pengyang ฉันดูคำตอบอื่น ๆ ของคุณและฉันจะบอกว่าสิ่งนี้ช่วยฉันได้มาก แต่ฉันมีสถานการณ์อื่นที่ฉันไม่รู้ว่าคุณชี้ให้เห็นวิธีที่ถูกต้องในการแก้ไขหรือไม่ ฉันต้องการหาวิธีเรียงสับเปลี่ยนทั้งหมดของคำเช่น 'ฮัลโลวีน' แต่พบว่าฉันต้องการรวมทั้ง 'L และทั้งสอง' E ในชุดผลลัพธ์ด้วย ในการวนซ้ำของฉันฉันวนซ้ำวิธีการของคุณให้ความยาวเพิ่มขึ้นกับการวนซ้ำแต่ละครั้ง (ความยาว ++) และคาดว่าจะได้รับความยาวเต็มของคำ HALLOWEEN (9 ตัวอักษร) ฉันจะได้ผลลัพธ์ 9 ตัวอักษรยาว ... แต่นี่ไม่ใช่กรณี: ฉันได้รับเพียง 7 (ละเว้น 1 1 และ 1 E)
MegaMark

ฉันอยากจะชี้ให้เห็นว่าฉันไม่ต้องการสถานการณ์ที่ฉันเห็น 9 'H เป็น' H 'ปรากฏขึ้นเพียงครั้งเดียวในคำว่า
MegaMark

4
@MegaMark ฟังก์ชั่นนี้ต้องใช้องค์ประกอบที่ไม่ซ้ำกัน ลองนี้:const string s = "HALLOWEEN"; var result = GetPermutations(Enumerable.Range(0, s.Length), s.Length).Select(t => t.Select(i => s[i]));
Pengyang

36

ที่นี่ฉันได้พบวิธีแก้ปัญหา มันเขียนใน Java แต่ฉันได้แปลงเป็น C # ฉันหวังว่ามันจะช่วยคุณ

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

นี่คือรหัสใน C #:

static void Main(string[] args)
{
    string str = "ABC";
    char[] charArry = str.ToCharArray();
    Permute(charArry, 0, 2);
    Console.ReadKey();
}

static void Permute(char[] arry, int i, int n)
{
    int j;
    if (i==n)
        Console.WriteLine(arry);
    else
    {
        for(j = i; j <=n; j++)
        {
            Swap(ref arry[i],ref arry[j]);
            Permute(arry,i+1,n);
            Swap(ref arry[i], ref arry[j]); //backtrack
        }
    }
}

static void Swap(ref char a, ref char b)
{
    char tmp;
    tmp = a;
    a=b;
    b = tmp;
}

มันถูกย้ายจากภาษาอื่นหรือไม่ +1 แน่นอนสำหรับภาพเพราะมันเพิ่มคุณค่าจริงๆ อย่างไรก็ตามรหัสตัวเองดูเหมือนว่ามีศักยภาพในการปรับปรุงที่แน่นอน ไม่จำเป็นต้องมีชิ้นส่วนเล็ก ๆ น้อย ๆ แต่ที่สำคัญที่สุดคือฉันรู้สึกได้ว่า C ++ เมื่อเราส่งบางสิ่งและทำสิ่งต่าง ๆ แทนการระบุพารามิเตอร์และดึงค่ากลับมา ในความเป็นจริงฉันใช้ภาพของคุณในการใช้รหัส C # - สไตล์ C # (สไตล์การรับรู้ส่วนบุคคลของฉันแน่นอน) และมันช่วยฉันอย่างมากดังนั้นเมื่อฉันจะโพสต์มันฉันจะขโมยมันจากคุณแน่นอน คุณมัน)
Konrad Viltersten

21

recursionไม่จำเป็นต้องที่นี่เป็นข้อมูลที่ดีเกี่ยวกับการแก้ปัญหานี้

var values1 = new[] { 1, 2, 3, 4, 5 };

foreach (var permutation in values1.GetPermutations())
{
    Console.WriteLine(string.Join(", ", permutation));
}

var values2 = new[] { 'a', 'b', 'c', 'd', 'e' };

foreach (var permutation in values2.GetPermutations())
{
    Console.WriteLine(string.Join(", ", permutation));
}

Console.ReadLine();

ฉันได้รับการใช้อัลกอริทึมสำหรับปีนี้ก็มีO (n) เวลาและพื้นที่ซับซ้อนในการคำนวณแต่ละเปลี่ยนแปลง

public static class SomeExtensions
{
    public static IEnumerable<IEnumerable<T>> GetPermutations<T>(this IEnumerable<T> enumerable)
    {
        var array = enumerable as T[] ?? enumerable.ToArray();

        var factorials = Enumerable.Range(0, array.Length + 1)
            .Select(Factorial)
            .ToArray();

        for (var i = 0L; i < factorials[array.Length]; i++)
        {
            var sequence = GenerateSequence(i, array.Length - 1, factorials);

            yield return GeneratePermutation(array, sequence);
        }
    }

    private static IEnumerable<T> GeneratePermutation<T>(T[] array, IReadOnlyList<int> sequence)
    {
        var clone = (T[]) array.Clone();

        for (int i = 0; i < clone.Length - 1; i++)
        {
            Swap(ref clone[i], ref clone[i + sequence[i]]);
        }

        return clone;
    }

    private static int[] GenerateSequence(long number, int size, IReadOnlyList<long> factorials)
    {
        var sequence = new int[size];

        for (var j = 0; j < sequence.Length; j++)
        {
            var facto = factorials[sequence.Length - j];

            sequence[j] = (int)(number / facto);
            number = (int)(number % facto);
        }

        return sequence;
    }

    static void Swap<T>(ref T a, ref T b)
    {
        T temp = a;
        a = b;
        b = temp;
    }

    private static long Factorial(int n)
    {
        long result = n;

        for (int i = 1; i < n; i++)
        {
            result = result * i;
        }

        return result;
    }
}

ทำงานนอกกรอบ!
revobtz

1
บางทีฉันไม่เข้าใจสัญกรณ์ O (n) N ไม่อ้างถึงจำนวน "วงใน" ที่จำเป็นในการทำให้อัลกอริทึมของคุณทำงานอย่างไร ดูเหมือนว่าฉันจะชอบถ้าคุณมีตัวเลข N ดูเหมือนว่ามันเป็น O (N * N!) (เพราะ N! ครั้งมันต้องทำสลับ N) นอกจากนี้ยังมีการคัดลอกอาร์เรย์มากมาย รหัสนี้ "เรียบร้อย" แต่ฉันจะไม่ใช้มัน
eric frazer

@ericfrazer แต่ละเปลี่ยนแปลงเพียงใช้สำเนาอาร์เรย์หนึ่งและO(N-1)ลำดับและสำหรับการแลกเปลี่ยนซึ่งเป็นO(N) O(N)และฉันยังคงใช้ในการผลิต แต่มี refactor เพื่อสร้างเพียงหนึ่งการเปลี่ยนแปลงที่ชอบ: ที่GetPermutation(i) 0 <= i <= N!-1ฉันยินดีที่จะใช้สิ่งที่มีประสิทธิภาพดีกว่านี้ดังนั้นโปรดโทรหาการอ้างอิงเพื่อสิ่งที่ดีกว่าทางเลือกส่วนใหญ่ที่ใช้O(N!)ในหน่วยความจำเพื่อให้คุณสามารถตรวจสอบได้เช่นกัน
Najera

11
void permute (char *str, int ptr) {
  int i, len;
  len = strlen(str);
  if (ptr == len) {
    printf ("%s\n", str);
    return;
  }

  for (i = ptr ; i < len ; i++) {
    swap (&str[ptr], &str[i]);
    permute (str, ptr + 1);
    swap (&str[ptr], &str[i]);
  }
}

คุณสามารถเขียนฟังก์ชั่นสลับเพื่อสลับตัวอักษร
สิ่งนี้จะถูกเรียกว่า permute (string, 0);


5
ดูเหมือนว่า C ไม่ใช่ C #
Jon Schneider

9

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

โปรดทราบว่าชุดของขนาด n มี n! n-พีชคณิต

pseudocode ต่อไปนี้ (จาก Wikipedia) เรียกด้วย k = 1 ... n! จะให้พีชคณิตทั้งหมด:

function permutation(k, s) {
    for j = 2 to length(s) {
        swap s[(k mod j) + 1] with s[j]; // note that our array is indexed starting at 1
        k := k / j; // integer division cuts off the remainder
    }
    return s;
}

นี่คือรหัส Python ที่เทียบเท่ากัน (สำหรับดัชนีอาร์เรย์ที่ใช้ 0):

def permutation(k, s):
    r = s[:]
    for j in range(2, len(s)+1):
        r[j-1], r[k%j] = r[k%j], r[j-1]
        k = k/j+1
    return r

5
นี่คือภาษาอะไร? คำถามถูกทำเครื่องหมาย C # ฉันไม่รู้ว่าk := k / j;ทำอะไร
Shawn Kovac

8

เวอร์ชันที่แก้ไขเล็กน้อยใน C # ที่ให้ผลตอบแทนที่ต้องการในอาร์เรย์ที่มีประเภทใด ๆ

    // USAGE: create an array of any type, and call Permutations()
    var vals = new[] {"a", "bb", "ccc"};
    foreach (var v in Permutations(vals))
        Console.WriteLine(string.Join(",", v)); // Print values separated by comma


public static IEnumerable<T[]> Permutations<T>(T[] values, int fromInd = 0)
{
    if (fromInd + 1 == values.Length)
        yield return values;
    else
    {
        foreach (var v in Permutations(values, fromInd + 1))
            yield return v;

        for (var i = fromInd + 1; i < values.Length; i++)
        {
            SwapValues(values, fromInd, i);
            foreach (var v in Permutations(values, fromInd + 1))
                yield return v;
            SwapValues(values, fromInd, i);
        }
    }
}

private static void SwapValues<T>(T[] values, int pos1, int pos2)
{
    if (pos1 != pos2)
    {
        T tmp = values[pos1];
        values[pos1] = values[pos2];
        values[pos2] = tmp;
    }
}

ข้อแม้เล็กน้อยหนึ่งข้อสำหรับการใช้งานนี้: จะทำงานได้อย่างถูกต้องหากคุณไม่พยายามเก็บค่าการแจงนับ หากคุณพยายามทำบางสิ่งเช่นนี้Permutations(vals).ToArray()คุณจะจบลงด้วยการอ้างอิง N ไปยังอาร์เรย์เดียวกัน หากคุณต้องการที่จะสามารถเก็บผลลัพธ์ที่คุณต้องสร้างสำเนาด้วยตนเอง เช่นPermutations(values).Select(v => (T[])v.Clone())
Pharap

8
class Program
{
    public static void Main(string[] args)
    {
        Permutation("abc");
    }

    static void Permutation(string rest, string prefix = "")
    {
        if (string.IsNullOrEmpty(rest)) Console.WriteLine(prefix);

        // Each letter has a chance to be permutated
        for (int i = 0; i < rest.Length; i++)
        {                
            Permutation(rest.Remove(i, 1), prefix + rest[i]);
        }
    }
}

1
สารละลายบ้า ขอบคุณ!
Cristian E.

7

ฉันชอบวิธีFBryant87เพราะมันง่าย น่าเสียดายที่มันไม่เหมือนกับ "วิธีแก้ปัญหา" อื่น ๆ อีกมากมายที่ไม่มีการเรียงสับเปลี่ยนทั้งหมดหรือเช่นจำนวนเต็มถ้ามันมีตัวเลขเดียวกันมากกว่าหนึ่งครั้ง รับ 656123 เป็นตัวอย่าง เส้น:

var tail = chars.Except(new List<char>(){c});

โดยใช้การยกเว้นที่จะทำให้เกิดขึ้นทั้งหมดจะถูกลบออกเช่นเมื่อ c = 6 ตัวเลขสองหลักจะถูกลบออกและเราจะเหลือเช่น 5123. เนื่องจากไม่มีการแก้ปัญหาผมพยายามแก้ปัญหานี้ผมตัดสินใจที่จะลองและแก้ปัญหาด้วยตัวเองโดยFBryant87 's รหัสเป็นฐาน นี่คือสิ่งที่ฉันมาด้วย:

private static List<string> FindPermutations(string set)
    {
        var output = new List<string>();
        if (set.Length == 1)
        {
            output.Add(set);
        }
        else
        {
            foreach (var c in set)
            {
                // Remove one occurrence of the char (not all)
                var tail = set.Remove(set.IndexOf(c), 1);
                foreach (var tailPerms in FindPermutations(tail))
                {
                    output.Add(c + tailPerms);
                }
            }
        }
        return output;
    }

ฉันเพียงแค่ลบเหตุการณ์ที่พบครั้งแรกโดยใช้. ลบและ .IndexOf ดูเหมือนว่าจะทำงานตามที่ตั้งใจไว้สำหรับการใช้งานของฉันอย่างน้อย ฉันแน่ใจว่ามันจะทำให้ฉลาดขึ้น

สิ่งหนึ่งที่ควรทราบ: รายการผลลัพธ์อาจมีรายการที่ซ้ำกันดังนั้นโปรดตรวจสอบให้แน่ใจว่าคุณได้ส่งคืนเมธอดเช่น HashSet แทนหรือลบรายการที่ซ้ำกันหลังจากการส่งคืนโดยใช้วิธีที่คุณชอบ


ทำงานเหมือนความงามอย่างสมบูรณ์ก่อนอื่นฉันพบว่าจัดการอักขระที่ซ้ำกัน +1
Jack Casey

5

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

http://www.cut-the-knot.org/do_you_know/AllPerm.shtml

C ++ และ Python ได้ในตัวnext_permutationและitertools.permutationsฟังก์ชั่นตามลำดับ


5

นี่คือการใช้งาน F # อย่างหมดจด:


let factorial i =
    let rec fact n x =
        match n with
        | 0 -> 1
        | 1 -> x
        | _ -> fact (n-1) (x*n)
    fact i 1

let swap (arr:'a array) i j = [| for k in 0..(arr.Length-1) -> if k = i then arr.[j] elif k = j then arr.[i] else arr.[k] |]

let rec permutation (k:int,j:int) (r:'a array) =
    if j = (r.Length + 1) then r
    else permutation (k/j+1, j+1) (swap r (j-1) (k%j))

let permutations (source:'a array) = seq { for k = 0 to (source |> Array.length |> factorial) - 1 do yield permutation (k,2) source }

สามารถปรับปรุงประสิทธิภาพได้อย่างมากโดยการเปลี่ยน swap เพื่อใช้ประโยชน์จากลักษณะที่ไม่แน่นอนของอาร์เรย์ CLR แต่การใช้งานนี้เป็นเธรดที่ปลอดภัยโดยคำนึงถึงอาร์เรย์ของแหล่งที่มาและอาจเป็นที่ต้องการในบางบริบท นอกจากนี้สำหรับอาร์เรย์ที่มีมากกว่า 16 องค์ประกอบ int จะต้องถูกแทนที่ด้วยชนิดที่มีความแม่นยำมากขึ้น / โดยพลการเนื่องจากแฟคทอเรียล 17 ส่งผลให้เกิดการโอเวอร์โฟลว์ของ int32


5

นี่คือวิธีง่ายๆใน c # โดยใช้การเรียกซ้ำ

void Main()
{
    string word = "abc";
    WordPermuatation("",word);
}

void WordPermuatation(string prefix, string word)
{
    int n = word.Length;
    if (n == 0) { Console.WriteLine(prefix); }
    else
    {
        for (int i = 0; i < n; i++)
        {
            WordPermuatation(prefix + word[i],word.Substring(0, i) + word.Substring(i + 1, n - (i+1)));
        }
    }
}

ขอบคุณสำหรับวิธีแก้ปัญหาที่ง่ายและสั้นมาก! :)
Kristaps Vilerts

4

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

เชือก

    static ICollection<string> result;

    public static ICollection<string> GetAllPermutations(string str, int outputLength)
    {
        result = new List<string>();
        MakePermutations(str.ToCharArray(), string.Empty, outputLength);
        return result;
    }

    private static void MakePermutations(
       char[] possibleArray,//all chars extracted from input
       string permutation,
       int outputLength//the length of output)
    {
         if (permutation.Length < outputLength)
         {
             for (int i = 0; i < possibleArray.Length; i++)
             {
                 var tempList = possibleArray.ToList<char>();
                 tempList.RemoveAt(i);
                 MakePermutations(tempList.ToArray(), 
                      string.Concat(permutation, possibleArray[i]), outputLength);
             }
         }
         else if (!result.Contains(permutation))
            result.Add(permutation);
    }

และสำหรับIntegerเพียงแค่เปลี่ยนวิธีการโทรและMakePermutations ()ยังคงไม่ถูกแตะต้อง:

    public static ICollection<int> GetAllPermutations(int input, int outputLength)
    {
        result = new List<string>();
        MakePermutations(input.ToString().ToCharArray(), string.Empty, outputLength);
        return result.Select(m => int.Parse(m)).ToList<int>();
    }

ตัวอย่างที่ 1: GetAllPermutations ("abc", 3); "abc" "acb" "bac" "bca" "cab" "cba"

ตัวอย่างที่ 2: GetAllPermutations ("abcd", 2); "ab" "ac" "ad" "ba" "bc" "bd" "ca" "cb" "cd" "da" "db" "dc"

ตัวอย่างที่ 3: GetAllPermutations (486,2) 48 46 84 86 64 68


ฉันชอบโซลูชันของคุณเพราะเข้าใจง่ายขอบคุณสำหรับสิ่งนั้น! แต่ผมเลือกที่จะไปกับที่หนึ่ง: stackoverflow.com/questions/756055/... สาเหตุที่ ToList, ToArray และ RemoveAt ล้วนมีความซับซ้อนของเวลาเป็น O (N) ดังนั้นโดยทั่วไปคุณจะต้องตรวจสอบองค์ประกอบทั้งหมดของคอลเลกชัน (ดูstackoverflow.com/a/15042066/1132522 ) เช่นเดียวกับ int ที่คุณจะไปตามองค์ประกอบทั้งหมดอีกครั้งในตอนท้ายเพื่อแปลงเป็น int ฉันยอมรับว่านี่จะไม่ส่งผลกระทบมากนักสำหรับ "abc" หรือ 486
Andrew

2

นี่คือฟังก์ชั่นที่จะพิมพ์การเปลี่ยนแปลงทั้งหมด ฟังก์ชั่นนี้ใช้ตรรกะอธิบายโดยปีเตอร์

public class Permutation
{
    //http://www.java2s.com/Tutorial/Java/0100__Class-Definition/RecursivemethodtofindallpermutationsofaString.htm

    public static void permuteString(String beginningString, String endingString)
    {           

        if (endingString.Length <= 1)
            Console.WriteLine(beginningString + endingString);
        else
            for (int i = 0; i < endingString.Length; i++)
            {

                String newString = endingString.Substring(0, i) + endingString.Substring(i + 1);

                permuteString(beginningString + endingString.ElementAt(i), newString);

            }
    }
}

    static void Main(string[] args)
    {

        Permutation.permuteString(String.Empty, "abc");
        Console.ReadLine();

    }

2

ด้านล่างคือการดำเนินการเปลี่ยนแปลงของฉัน ไม่ต้องสนใจชื่อตัวแปรเพราะฉันทำเพื่อความสนุก :)

class combinations
{
    static void Main()
    {

        string choice = "y";
        do
        {
            try
            {
                Console.WriteLine("Enter word :");
                string abc = Console.ReadLine().ToString();
                Console.WriteLine("Combinatins for word :");
                List<string> final = comb(abc);
                int count = 1;
                foreach (string s in final)
                {
                    Console.WriteLine("{0} --> {1}", count++, s);
                }
                Console.WriteLine("Do you wish to continue(y/n)?");
                choice = Console.ReadLine().ToString();
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc);
            }
        } while (choice == "y" || choice == "Y");
    }

    static string swap(string test)
    {
        return swap(0, 1, test);
    }

    static List<string> comb(string test)
    {
        List<string> sec = new List<string>();
        List<string> first = new List<string>();
        if (test.Length == 1) first.Add(test);
        else if (test.Length == 2) { first.Add(test); first.Add(swap(test)); }
        else if (test.Length > 2)
        {
            sec = generateWords(test);
            foreach (string s in sec)
            {
                string init = s.Substring(0, 1);
                string restOfbody = s.Substring(1, s.Length - 1);

                List<string> third = comb(restOfbody);
                foreach (string s1 in third)
                {
                    if (!first.Contains(init + s1)) first.Add(init + s1);
                }


            }
        }

        return first;
    }

    static string ShiftBack(string abc)
    {
        char[] arr = abc.ToCharArray();
        char temp = arr[0];
        string wrd = string.Empty;
        for (int i = 1; i < arr.Length; i++)
        {
            wrd += arr[i];
        }

        wrd += temp;
        return wrd;
    }

    static List<string> generateWords(string test)
    {
        List<string> final = new List<string>();
        if (test.Length == 1)
            final.Add(test);
        else
        {
            final.Add(test);
            string holdString = test;
            while (final.Count < test.Length)
            {
                holdString = ShiftBack(holdString);
                final.Add(holdString);
            }
        }

        return final;
    }

    static string swap(int currentPosition, int targetPosition, string temp)
    {
        char[] arr = temp.ToCharArray();
        char t = arr[currentPosition];
        arr[currentPosition] = arr[targetPosition];
        arr[targetPosition] = t;
        string word = string.Empty;
        for (int i = 0; i < arr.Length; i++)
        {
            word += arr[i];

        }

        return word;

    }
}

2

นี่เป็นตัวอย่างระดับสูงที่ฉันเขียนซึ่งแสดงให้เห็นถึงคำอธิบายภาษามนุษย์ที่ปีเตอร์ให้:

    public List<string> FindPermutations(string input)
    {
        if (input.Length == 1)
            return new List<string> { input };
        var perms = new List<string>();
        foreach (var c in input)
        {
            var others = input.Remove(input.IndexOf(c), 1);
            perms.AddRange(FindPermutations(others).Select(perm => c + perm));
        }
        return perms;
    }

วิธีแก้ปัญหานี้มีข้อบกพร่องจริง ๆ ถ้าชุดสตริงมีอักขระซ้ำ ๆ จะล้มเหลว ตัวอย่างเช่นในคำว่า 'ทดสอบ' คำสั่งยกเว้นจะลบทั้งสองอินสแตนซ์ของ 't' แทนเพียงแค่ตัวแรกและตัวสุดท้ายเมื่อจำเป็น
Middas

1
@ มิดเดิ้ลเห็นดีโชคดีที่กอดมากับวิธีแก้ปัญหานี้
FBryant87

1

หากประสิทธิภาพและหน่วยความจำเป็นปัญหาฉันขอแนะนำให้ใช้งานอย่างมีประสิทธิภาพมาก ตามอัลกอริทึมของฮีปใน Wikipediaมันควรจะเร็วที่สุด หวังว่ามันจะเหมาะกับความต้องการของคุณ :-)!

การเปรียบเทียบสิ่งนี้กับการนำ Linq มาใช้เป็นเวลา 10! (รวมรหัส):

  • สิ่งนี้: 36288000 รายการใน 235 มิลลิวินาที
  • Linq: 36288000 รายการใน 50051 มิลลิวินาที

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Text;
    
    namespace WpfPermutations
    {
        /// <summary>
        /// EO: 2016-04-14
        /// Generator of all permutations of an array of anything.
        /// Base on Heap's Algorithm. See: https://en.wikipedia.org/wiki/Heap%27s_algorithm#cite_note-3
        /// </summary>
        public static class Permutations
        {
            /// <summary>
            /// Heap's algorithm to find all pmermutations. Non recursive, more efficient.
            /// </summary>
            /// <param name="items">Items to permute in each possible ways</param>
            /// <param name="funcExecuteAndTellIfShouldStop"></param>
            /// <returns>Return true if cancelled</returns> 
            public static bool ForAllPermutation<T>(T[] items, Func<T[], bool> funcExecuteAndTellIfShouldStop)
            {
                int countOfItem = items.Length;
    
                if (countOfItem <= 1)
                {
                    return funcExecuteAndTellIfShouldStop(items);
                }
    
                var indexes = new int[countOfItem];
                for (int i = 0; i < countOfItem; i++)
                {
                    indexes[i] = 0;
                }
    
                if (funcExecuteAndTellIfShouldStop(items))
                {
                    return true;
                }
    
                for (int i = 1; i < countOfItem;)
                {
                    if (indexes[i] < i)
                    { // On the web there is an implementation with a multiplication which should be less efficient.
                        if ((i & 1) == 1) // if (i % 2 == 1)  ... more efficient ??? At least the same.
                        {
                            Swap(ref items[i], ref items[indexes[i]]);
                        }
                        else
                        {
                            Swap(ref items[i], ref items[0]);
                        }
    
                        if (funcExecuteAndTellIfShouldStop(items))
                        {
                            return true;
                        }
    
                        indexes[i]++;
                        i = 1;
                    }
                    else
                    {
                        indexes[i++] = 0;
                    }
                }
    
                return false;
            }
    
            /// <summary>
            /// This function is to show a linq way but is far less efficient
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="list"></param>
            /// <param name="length"></param>
            /// <returns></returns>
            static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> list, int length)
            {
                if (length == 1) return list.Select(t => new T[] { t });
    
                return GetPermutations(list, length - 1)
                    .SelectMany(t => list.Where(e => !t.Contains(e)),
                        (t1, t2) => t1.Concat(new T[] { t2 }));
            }
    
            /// <summary>
            /// Swap 2 elements of same type
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="a"></param>
            /// <param name="b"></param>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static void Swap<T>(ref T a, ref T b)
            {
                T temp = a;
                a = b;
                b = temp;
            }
    
            /// <summary>
            /// Func to show how to call. It does a little test for an array of 4 items.
            /// </summary>
            public static void Test()
            {
                ForAllPermutation("123".ToCharArray(), (vals) =>
                {
                    Debug.Print(String.Join("", vals));
                    return false;
                });
    
                int[] values = new int[] { 0, 1, 2, 4 };
    
                Debug.Print("Non Linq");
                ForAllPermutation(values, (vals) =>
                {
                    Debug.Print(String.Join("", vals));
                    return false;
                });
    
                Debug.Print("Linq");
                foreach(var v in GetPermutations(values, values.Length))
                {
                    Debug.Print(String.Join("", v));
                }
    
                // Performance
                int count = 0;
    
                values = new int[10];
                for(int n = 0; n < values.Length; n++)
                {
                    values[n] = n;
                }
    
                Stopwatch stopWatch = new Stopwatch();
                stopWatch.Reset();
                stopWatch.Start();
    
                ForAllPermutation(values, (vals) =>
                {
                    foreach(var v in vals)
                    {
                        count++;
                    }
                    return false;
                });
    
                stopWatch.Stop();
                Debug.Print($"Non Linq {count} items in {stopWatch.ElapsedMilliseconds} millisecs");
    
                count = 0;
                stopWatch.Reset();
                stopWatch.Start();
    
                foreach (var vals in GetPermutations(values, values.Length))
                {
                    foreach (var v in vals)
                    {
                        count++;
                    }
                }
    
                stopWatch.Stop();
                Debug.Print($"Linq {count} items in {stopWatch.ElapsedMilliseconds} millisecs");
    
            }
        }
    }

1

นี่คือโซลูชันของฉันใน JavaScript (NodeJS) แนวคิดหลักคือการที่เรานำองค์ประกอบหนึ่งครั้ง "ลบ" จากสตริงที่แตกต่างกันของตัวละครที่เหลือและแทรกองค์ประกอบที่ด้านหน้า

function perms (string) {
  if (string.length == 0) {
    return [];
  }
  if (string.length == 1) {
    return [string];
  }
  var list = [];
  for(var i = 0; i < string.length; i++) {
    var invariant = string[i];
    var rest = string.substr(0, i) + string.substr(i + 1);
    var newPerms = perms(rest);
    for (var j = 0; j < newPerms.length; j++) {
      list.push(invariant + newPerms[j]);
    }
  }
  return list;
}

module.exports = perms;

และนี่คือการทดสอบ:

require('should');
var permutations = require('../src/perms');

describe('permutations', function () {
  it('should permute ""', function () {
    permutations('').should.eql([]);
  })

  it('should permute "1"', function () {
    permutations('1').should.eql(['1']);
  })

  it('should permute "12"', function () {
    permutations('12').should.eql(['12', '21']);
  })

  it('should permute "123"', function () {
    var expected = ['123', '132', '321', '213', '231', '312'];
    var actual = permutations('123');
    expected.forEach(function (e) {
      actual.should.containEql(e);
    })
  })

  it('should permute "1234"', function () {
    // Wolfram Alpha FTW!
    var expected = ['1234', '1243', '1324', '1342', '1423', '1432', '2134', '2143', '2314', '2341', '2413', '2431', '3124', '3142', '3214', '3241', '3412', '3421', '4123', '4132'];
    var actual = permutations('1234');
    expected.forEach(function (e) {
      actual.should.containEql(e);
    })
  })
})

1

นี่คือทางออกที่ง่ายที่สุดที่ฉันคิดได้:

let rec distribute e = function
  | [] -> [[e]]
  | x::xs' as xs -> (e::xs)::[for xs in distribute e xs' -> x::xs]

let permute xs = Seq.fold (fun ps x -> List.collect (distribute x) ps) [[]] xs

distributeฟังก์ชั่นใช้เวลาองค์ประกอบใหม่eและnรายชื่อองค์ประกอบและส่งกลับรายการของn+1รายการแต่ละที่ได้eแทรกในสถานที่ที่แตกต่างกัน ตัวอย่างเช่นการแทรก10แต่ละตำแหน่งที่เป็นไปได้ทั้งสี่ในรายการ[1;2;3]:

> distribute 10 [1..3];;
val it : int list list =
  [[10; 1; 2; 3]; [1; 10; 2; 3]; [1; 2; 10; 3]; [1; 2; 3; 10]]

permuteฟังก์ชั่นพับมากกว่าองค์ประกอบในทางกลับกันกระจายกว่าพีชคณิตสะสมเพื่อให้ห่างไกลสูงสุดในพีชคณิตทั้งหมด ตัวอย่างเช่นการเรียงลำดับ 6 รายการ[1;2;3]:

> permute [1;2;3];;
val it : int list list =
  [[3; 2; 1]; [2; 3; 1]; [2; 1; 3]; [3; 1; 2]; [1; 3; 2]; [1; 2; 3]]

การเปลี่ยนค่าfolda scanเพื่อรักษาระดับกลางให้แสงบางอย่างเกี่ยวกับวิธีการเรียงสับเปลี่ยนสร้างองค์ประกอบในเวลา:

> Seq.scan (fun ps x -> List.collect (distribute x) ps) [[]] [1..3];;
val it : seq<int list list> =
  seq
    [[[]]; [[1]]; [[2; 1]; [1; 2]];
     [[3; 2; 1]; [2; 3; 1]; [2; 1; 3]; [3; 1; 2]; [1; 3; 2]; [1; 2; 3]]]

1

แสดงรายการการเรียงสับเปลี่ยนของสตริง หลีกเลี่ยงการทำซ้ำเมื่ออักขระซ้ำ:

using System;
using System.Collections;

class Permutation{
  static IEnumerable Permutations(string word){
    if (word == null || word.Length <= 1) {
      yield return word;
      yield break;
    }

    char firstChar = word[0];
    foreach( string subPermute in Permutations (word.Substring (1)) ) {
      int indexOfFirstChar = subPermute.IndexOf (firstChar);
      if (indexOfFirstChar == -1) indexOfFirstChar = subPermute.Length;

      for( int index = 0; index <= indexOfFirstChar; index++ )
        yield return subPermute.Insert (index, new string (firstChar, 1));
    }
  }

  static void Main(){
    foreach( var permutation in Permutations ("aab") )
      Console.WriteLine (permutation);
  }
}

2
ด้วยโซลูชันการทำงานจำนวนมากที่มีอยู่แล้วคุณอาจต้องการอธิบายสิ่งที่ทำให้โซลูชันของคุณโดดเด่นจากโซลูชันอื่น ๆ ทั้งหมดที่นี่
nvoigt

หลีกเลี่ยงการทำซ้ำเมื่ออักขระซ้ำ (โดย chindirala สำหรับคำตอบอื่น) สำหรับ "aab": aab aba baa
Val

1

สร้างโดยวิธีการแก้ปัญหาของ @ Peter นี่เป็นรุ่นที่ประกาศPermutations()วิธีการขยายส่วนขยายสไตล์ LINQ ที่ใช้งานIEnumerable<T>ได้จริง

การใช้งาน (บนตัวอักษรสตริง):

foreach (var permutation in "abc".Permutations())
{
    Console.WriteLine(string.Join(", ", permutation));
}

ขาออก:

a, b, c
a, c, b
b, a, c
b, c, a
c, b, a
c, a, b

หรือประเภทคอลเลกชันอื่น ๆ :

foreach (var permutation in (new[] { "Apples", "Oranges", "Pears"}).Permutations())
{
    Console.WriteLine(string.Join(", ", permutation));
}

ขาออก:

Apples, Oranges, Pears
Apples, Pears, Oranges
Oranges, Apples, Pears
Oranges, Pears, Apples
Pears, Oranges, Apples
Pears, Apples, Oranges
using System;
using System.Collections.Generic;
using System.Linq;

public static class PermutationExtension
{
    public static IEnumerable<T[]> Permutations<T>(this IEnumerable<T> source)
    {
        var sourceArray = source.ToArray();
        var results = new List<T[]>();
        Permute(sourceArray, 0, sourceArray.Length - 1, results);
        return results;
    }

    private static void Swap<T>(ref T a, ref T b)
    {
        T tmp = a;
        a = b;
        b = tmp;
    }

    private static void Permute<T>(T[] elements, int recursionDepth, int maxDepth, ICollection<T[]> results)
    {
        if (recursionDepth == maxDepth)
        {
            results.Add(elements.ToArray());
            return;
        }

        for (var i = recursionDepth; i <= maxDepth; i++)
        {
            Swap(ref elements[recursionDepth], ref elements[i]);
            Permute(elements, recursionDepth + 1, maxDepth, results);
            Swap(ref elements[recursionDepth], ref elements[i]);
        }
    }
}

0

นี่คือฟังก์ชั่นที่จะพิมพ์การเรียงสับเปลี่ยนทั้งหมดซ้ำ

public void Permutations(string input, StringBuilder sb)
    {
        if (sb.Length == input.Length)
        {
            Console.WriteLine(sb.ToString());
            return;
        }

        char[] inChar = input.ToCharArray();

        for (int i = 0; i < input.Length; i++)
        {
            if (!sb.ToString().Contains(inChar[i]))
            {
                sb.Append(inChar[i]);
                Permutations(input, sb);    
                RemoveChar(sb, inChar[i]);
            }
        }
    }

private bool RemoveChar(StringBuilder input, char toRemove)
    {
        int index = input.ToString().IndexOf(toRemove);
        if (index >= 0)
        {
            input.Remove(index, 1);
            return true;
        }
        return false;
    }

0
class Permutation
{
    public static List<string> Permutate(string seed, List<string> lstsList)
    {
        loopCounter = 0;
        // string s="\w{0,2}";
        var lstStrs = PermuateRecursive(seed);

        Trace.WriteLine("Loop counter :" + loopCounter);
        return lstStrs;
    }

    // Recursive function to find permutation
    private static List<string> PermuateRecursive(string seed)
    {
        List<string> lstStrs = new List<string>();

        if (seed.Length > 2)
        {
            for (int i = 0; i < seed.Length; i++)
            {
                str = Swap(seed, 0, i);

                PermuateRecursive(str.Substring(1, str.Length - 1)).ForEach(
                    s =>
                    {
                        lstStrs.Add(str[0] + s);
                        loopCounter++;
                    });
                ;
            }
        }
        else
        {
            lstStrs.Add(seed);
            lstStrs.Add(Swap(seed, 0, 1));
        }
        return lstStrs;
    }
    //Loop counter variable to count total number of loop execution in various functions
    private static int loopCounter = 0;

    //Non recursive  version of permuation function
    public static List<string> Permutate(string seed)
    {
        loopCounter = 0;
        List<string> strList = new List<string>();
        strList.Add(seed);
        for (int i = 0; i < seed.Length; i++)
        {
            int count = strList.Count;
            for (int j = i + 1; j < seed.Length; j++)
            {
                for (int k = 0; k < count; k++)
                {
                    strList.Add(Swap(strList[k], i, j));
                    loopCounter++;
                }
            }
        }
        Trace.WriteLine("Loop counter :" + loopCounter);
        return strList;
    }

    private static string Swap(string seed, int p, int p2)
    {
        Char[] chars = seed.ToCharArray();
        char temp = chars[p2];
        chars[p2] = chars[p];
        chars[p] = temp;
        return new string(chars);
    }
}

0

นี่คือคำตอบ C # ซึ่งง่ายขึ้นเล็กน้อย

public static void StringPermutationsDemo()
{
    strBldr = new StringBuilder();

    string result = Permute("ABCD".ToCharArray(), 0);
    MessageBox.Show(result);
}     

static string Permute(char[] elementsList, int startIndex)
{
    if (startIndex == elementsList.Length)
    {
        foreach (char element in elementsList)
        {
            strBldr.Append(" " + element);
        }
        strBldr.AppendLine("");
    }
    else
    {
        for (int tempIndex = startIndex; tempIndex <= elementsList.Length - 1; tempIndex++)
        {
            Swap(ref elementsList[startIndex], ref elementsList[tempIndex]);

            Permute(elementsList, (startIndex + 1));

            Swap(ref elementsList[startIndex], ref elementsList[tempIndex]);
        }
    }

    return strBldr.ToString();
}

static void Swap(ref char Char1, ref char Char2)
{
    char tempElement = Char1;
    Char1 = Char2;
    Char2 = tempElement;
}

เอาท์พุท:

1 2 3
1 3 2

2 1 3
2 3 1

3 2 1
3 1 2

0

นี่คือทางออกของฉันซึ่งฉันเข้าใจได้ง่าย

class ClassicPermutationProblem
{
    ClassicPermutationProblem() { }

    private static void PopulatePosition<T>(List<List<T>> finalList, List<T> list, List<T> temp, int position)
    {
         foreach (T element in list)
         {
             List<T> currentTemp = temp.ToList();
             if (!currentTemp.Contains(element))
                currentTemp.Add(element);
             else
                continue;

             if (position == list.Count)
                finalList.Add(currentTemp);
             else
                PopulatePosition(finalList, list, currentTemp, position + 1);
        }
    }

    public static List<List<int>> GetPermutations(List<int> list)
    {
        List<List<int>> results = new List<List<int>>();
        PopulatePosition(results, list, new List<int>(), 1);
        return results;
     }
}

static void Main(string[] args)
{
    List<List<int>> results = ClassicPermutationProblem.GetPermutations(new List<int>() { 1, 2, 3 });
}

0

นี่คืออีกหนึ่งการดำเนินการของ algo ที่กล่าวถึง

public class Program
{
    public static void Main(string[] args)
    {
        string str = "abcefgh";
        var astr = new Permutation().GenerateFor(str);
        Console.WriteLine(astr.Length);
        foreach(var a in astr)
        {
            Console.WriteLine(a);
        }
        //a.ForEach(Console.WriteLine);
    }
}

class Permutation
{
    public string[] GenerateFor(string s)
    {  

        if(s.Length == 1)
        {

            return new []{s}; 
        }

        else if(s.Length == 2)
        {

            return new []{s[1].ToString()+s[0].ToString(),s[0].ToString()+s[1].ToString()};

        }

        var comb = new List<string>();

        foreach(var c in s)
        {

            string cStr = c.ToString();

            var sToProcess = s.Replace(cStr,"");
            if (!string.IsNullOrEmpty(sToProcess) && sToProcess.Length>0)
            {
                var conCatStr = GenerateFor(sToProcess);



                foreach(var a in conCatStr)
                {
                    comb.Add(c.ToString()+a);
                }


            }
        }
        return comb.ToArray();

    }
}

new Permutation().GenerateFor("aba")ผลลัพธ์string[4] { "ab", "baa", "baa", "ab" }
Atomosk

0
    //Generic C# Method
            private static List<T[]> GetPerms<T>(T[] input, int startIndex = 0)
            {
                var perms = new List<T[]>();

                var l = input.Length - 1;

                if (l == startIndex)
                    perms.Add(input);
                else
                {

                    for (int i = startIndex; i <= l; i++)
                    {
                        var copy = input.ToArray(); //make copy

                        var temp = copy[startIndex];

                        copy[startIndex] = copy[i];
                        copy[i] = temp;

                        perms.AddRange(GetPerms(copy, startIndex + 1));

                    }
                }

                return perms;
            }

            //usages
            char[] charArray = new char[] { 'A', 'B', 'C' };
            var charPerms = GetPerms(charArray);


            string[] stringArray = new string[] { "Orange", "Mango", "Apple" };
            var stringPerms = GetPerms(stringArray);


            int[] intArray = new int[] { 1, 2, 3 };
            var intPerms = GetPerms(intArray);

มันจะดีถ้าคุณสามารถอธิบายเพิ่มเติมเล็กน้อยเกี่ยวกับวิธีการทำงานของรหัสนี้แทนที่จะปล่อยไว้ที่นี่เพียงอย่างเดียว
iBug

-1
    /// <summary>
    /// Print All the Permutations.
    /// </summary>
    /// <param name="inputStr">input string</param>
    /// <param name="strLength">length of the string</param>
    /// <param name="outputStr">output string</param>
    private void PrintAllPermutations(string inputStr, int strLength,string outputStr, int NumberOfChars)
    {
        //Means you have completed a permutation.
        if (outputStr.Length == NumberOfChars)
        {
            Console.WriteLine(outputStr);                
            return;
        }

        //For loop is used to print permutations starting with every character. first print all the permutations starting with a,then b, etc.
        for(int i=0 ; i< strLength; i++)
        {
            // Recursive call : for a string abc = a + perm(bc). b+ perm(ac) etc.
            PrintAllPermutations(inputStr.Remove(i, 1), strLength - 1, outputStr + inputStr.Substring(i, 1), 4);
        }
    }        
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.