Bir dizenin olası tüm permütasyonlarının listesini oluşturun


Yanıtlar:


70

Bunu yapmanın birkaç yolu vardır. Yaygın yöntemlerde özyineleme, not veya dinamik programlama kullanılır. Temel fikir, uzunluk 1'in tüm dizelerinin bir listesini üretmeniz, daha sonra her yinelemede, son yinelemede üretilen tüm dizeler için, dizedeki her karakterle birleştirilen dizeyi ayrı ayrı eklemenizdir. (aşağıdaki koddaki değişken dizin son ve sonraki yinelemenin başlangıcını takip eder)

Bazı sözde kod:

list = originalString.split('')
index = (0,0)
list = [""]
for iteration n in 1 to y:
  index = (index[1], len(list))
  for string s in list.subset(index[0] to end):
    for character c in originalString:
      list.add(s + c)

daha sonra, x'den küçük tüm dizeleri kaldırmanız gerekir; bunlar listedeki ilk (x-1) * len (originalString) girişler olur.


4
Neden ilk önce elemanlar listesini saklayın ve sonra temizleyin? (sözde koddaki 1. ve 3. satırlara atıfta bulunur).
Håvard Geithus

6
Y (satır 4) nedir?
Jaseem

7
@Jaseem Şu sorudan: " uzunluk olarak x ve y karakterleri arasındaki bir dizenin tüm olası permütasyonları "
ck_

39

Geri izlemeyi kullanmak daha iyidir

#include <stdio.h>
#include <string.h>

void swap(char *a, char *b) {
    char temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

void print(char *a, int i, int n) {
    int j;
    if(i == n) {
        printf("%s\n", a);
    } else {
        for(j = i; j <= n; j++) {
            swap(a + i, a + j);
            print(a, i + 1, n);
            swap(a + i, a + j);
        }
    }
}

int main(void) {
    char a[100];
    gets(a);
    print(a, 0, strlen(a) - 1);
    return 0;
}

3
En iyi çözüm everrrrrrrrr
GrowinMan

25

Bir sürü ip alacaksın, bu kesin ...

\ Sum_ {i = x} ^ y {\ frac {R!} {{(N)}!}}
Burada x ve y bunları nasıl tanımladığınız ve r, seçtiğimiz karakter sayısıdır - eğer sizi doğru anlıyorsam. Bunları kesinlikle gerektiği gibi üretmeli ve özensizleşmemeli ve bir güç kümesi oluşturmalı ve sonra dizelerin uzunluğunu filtrelemelisiniz.

Aşağıdakiler kesinlikle bunları üretmenin en iyi yolu değil, ama ilginç bir kenara, hiç de az değil.

Knuth (cilt 4, fascicle 2, 7.2.1.3) bize, (s, t)-kombinasyonunun tekrar ile bir defada alınan s + 1 şeye eşdeğer olduğunu söyler - bir (s, t)-kombinasyonunun kullandığı gösterim Eşittir {t \ seçin {s + t}. İlk önce her bir (s, t) kombinasyonunu ikili biçimde (yani, uzunluk (s + t)) oluşturarak ve her 1'in solundaki 0 ​​sayısını sayarak çözebiliriz.

10001000011101 -> permütasyon olur: {0, 3, 4, 4, 4, 1}


15

Knuth, Python örneğine göre özyinelemesiz çözüm:

def nextPermutation(perm):
    k0 = None
    for i in range(len(perm)-1):
        if perm[i]<perm[i+1]:
            k0=i
    if k0 == None:
        return None

    l0 = k0+1
    for i in range(k0+1, len(perm)):
        if perm[k0] < perm[i]:
            l0 = i

    perm[k0], perm[l0] = perm[l0], perm[k0]
    perm[k0+1:] = reversed(perm[k0+1:])
    return perm

perm=list("12345")
while perm:
    print perm
    perm = nextPermutation(perm)

2
Aslında bu yok değil dize sıralanmış değilken çalışır. Birlikte denerseniz "54321"sadece TEK dize (kendisi) gösterdi.
tonjo

1
İlginç olan nextPermutation(), vatansızdır - sadece permütasyon için girişi alır ve endeksler yinelemeden yinelemeye kadar korunmaz. İlk girişin sıralandığını varsayarak ve siparişin nerede korunduğuna bağlı olarak indeksleri ( k0ve l0) bularak yapabilir . "54321" -> "12345" gibi bir girdiyi sıralamak, bu algoritmanın beklenen tüm permütasyonları bulmasına izin verecektir. Ancak, oluşturduğu her permütasyon için bu indeksleri yeniden bulmak için fazladan ekstra iş yaptığı için, bunu tekrarlamalı olarak yapmanın daha etkili yolları vardır.
spaaarky21

13

İstediğiniz şeyin bir parçasını yapmak için bir algoritma tanımlayan " Bir Kümenin Alt Kümelerini Etkin Bir Şekilde Numaralandırma" konusuna bakabilirsiniz - x uzunluğundan y'ye kadar tüm N karakter alt kümelerini hızlı bir şekilde oluşturun. C'de bir uygulama içerir.

Her alt küme için yine de tüm permütasyonları oluşturmanız gerekir. Örneğin, "abcde" den 3 karakter istiyorsanız, bu algoritma size "abc", "abd", "abe" verir, ancak her birinin "acb", "bac" almasına izin vermeniz gerekir, "bca" vb.


13

Sarp'ın cevabına dayanan bazı çalışan Java kodları :

public class permute {

    static void permute(int level, String permuted,
                    boolean used[], String original) {
        int length = original.length();
        if (level == length) {
            System.out.println(permuted);
        } else {
            for (int i = 0; i < length; i++) {
                if (!used[i]) {
                    used[i] = true;
                    permute(level + 1, permuted + original.charAt(i),
                       used, original);
                    used[i] = false;
                }
            }
        }
    }

    public static void main(String[] args) {
        String s = "hello";
        boolean used[] = {false, false, false, false, false};
        permute(0, "", used, s);
    }
}

Yorum olarak, tekrarlanan karakterlere sahip bir dize için bunun benzersiz permütasyonlar üretmeyeceğini unutmayın. Bu bir karma ile çözülebilir, ancak bu uzun dizelerle ilgili bir sorun olabilir.
Glenn

8
Java'da dizeler değiştirilemediğinden, daha hızlı çalışmasını sağlamak için dizeler yerine char dizileri kullanmak isteyebilirsiniz.
Abhijeet Kashnia

13

İşte C # 'da basit bir çözüm.

Belirli bir dizenin yalnızca belirgin permütasyonlarını üretir.

    static public IEnumerable<string> permute(string word)
    {
        if (word.Length > 1)
        {

            char character = word[0];
            foreach (string subPermute in permute(word.Substring(1)))
            {

                for (int index = 0; index <= subPermute.Length; index++)
                {
                    string pre = subPermute.Substring(0, index);
                    string post = subPermute.Substring(index);

                    if (post.Contains(character))
                            continue;                       

                    yield return pre + character + post;
                }

            }
        }
        else
        {
            yield return word;
        }
    }

12

Burada çok iyi cevaplar var. Ayrıca C ++ 'da çok basit bir özyinelemeli çözüm öneririm.

#include <string>
#include <iostream>

template<typename Consume>
void permutations(std::string s, Consume consume, std::size_t start = 0) {
    if (start == s.length()) consume(s);
    for (std::size_t i = start; i < s.length(); i++) {
        std::swap(s[start], s[i]);
        permutations(s, consume, start + 1);
    }
}

int main(void) {
    std::string s = "abcd";
    permutations(s, [](std::string s) {
        std::cout << s << std::endl;
    });
}

Not : tekrarlanan karakterlere sahip dizeler benzersiz permütasyonlar üretmez.


9

Ruby'de bunu çabucak çırptım:

def perms(x, y, possible_characters)
  all = [""]
  current_array = all.clone
  1.upto(y) { |iteration|
    next_array = []
    current_array.each { |string|
      possible_characters.each { |c|
        value = string + c
        next_array.insert next_array.length, value
        all.insert all.length, value
      }
    }
    current_array = next_array
  }
  all.delete_if { |string| string.length < x }
end

Dahili permütasyon tipi fonksiyonlar için dil API'sine bakabilirsiniz ve daha optimize edilmiş kod yazabilirsiniz, ancak sayılar bu kadar yüksekse, çok fazla sonuç almanın bir yolu olduğundan emin değilim .

Her neyse, kodun arkasındaki fikir 0 uzunluk dizesiyle başlar, sonra Z uzunluğunun tüm dizelerini takip edin, burada Z yinelemedeki geçerli boyuttur. Ardından, her dizeyi gözden geçirin ve her karakteri her dizeye ekleyin. Sonunda, x eşiğinin altında olanları kaldırın ve sonucu döndürün.

Potansiyel olarak anlamsız girdi (null karakter listesi, garip x ve y değerleri, vb.) İle test etmedim.


11
Bu kod YANLIŞ. Tekrarlanan karakterlere sahip olanlar gibi geçersiz permütasyonlar oluşturur. Örneğin, "abc" dizesi için, 3 boyutunda şu permütasyonları oluşturur: ["aaa", "aab", "aac", "aba", "abb", "abc", "aca", "acb", "acc", "baa", "bab", "bac", "bba", "bbb", "bbc", "bca", "bcb", "bcc", "caa", "kabin", "cac "," cba "," cbb "," cbc "," cca "," ccb "," ccc "]. Bu yanlış.
pmc255

8

Mike'ın Ruby versiyonunun Common Lisp'e çevirisi:

(defun perms (x y original-string)
  (loop with all = (list "")
        with current-array = (list "")
        for iteration from 1 to y
        do (loop with next-array = nil
                 for string in current-array
                 do (loop for c across original-string
                          for value = (concatenate 'string string (string c))
                          do (push value next-array)
                             (push value all))
                    (setf current-array (reverse next-array)))
        finally (return (nreverse (delete-if #'(lambda (el) (< (length el) x)) all)))))

Ve biraz daha kısa ve daha fazla döngü tesisi özellikleri kullanan başka bir sürüm:

(defun perms (x y original-string)
  (loop repeat y
        collect (loop for string in (or (car (last sets)) (list ""))
                      append (loop for c across original-string
                                   collect (concatenate 'string string (string c)))) into sets
        finally (return (loop for set in sets
                              append (loop for el in set when (>= (length el) x) collect el)))))

8

İşte basit bir kelime C # özyinelemeli çözüm:

Yöntem:

public ArrayList CalculateWordPermutations(string[] letters, ArrayList words, int index)
        {
            bool finished = true;
            ArrayList newWords = new ArrayList();
            if (words.Count == 0)
            {
                foreach (string letter in letters)
                {
                    words.Add(letter);
                }
            }

            for(int j=index; j<words.Count; j++)
            {
                string word = (string)words[j];
                for(int i =0; i<letters.Length; i++)
                {
                    if(!word.Contains(letters[i]))
                    {
                        finished = false;
                        string newWord = (string)word.Clone();
                        newWord += letters[i];
                        newWords.Add(newWord);
                    }
                }
            }

            foreach (string newWord in newWords)
            {   
                words.Add(newWord);
            }

            if(finished  == false)
            {
                CalculateWordPermutations(letters, words, words.Count - newWords.Count);
            }
            return words;
        }

Arayan:

string[] letters = new string[]{"a","b","c"};
ArrayList words = CalculateWordPermutations(letters, new ArrayList(), 0);

8

... ve işte C versiyonu:

void permute(const char *s, char *out, int *used, int len, int lev)
{
    if (len == lev) {
        out[lev] = '\0';
        puts(out);
        return;
    }

    int i;
    for (i = 0; i < len; ++i) {
        if (! used[i])
            continue;

        used[i] = 1;
        out[lev] = s[i];
        permute(s, out, used, len, lev + 1);
        used[i] = 0;
    }
    return;
}

8

permütasyon (ABC) -> A.perm (BC) -> A.perm [B.perm (C)] -> A.perm [( * B C), (C B * )] -> [( * A BC ), (B A C), (BC A * ), ( * A CB), (C A B), (CB A * )] Her alfabe eklerken yinelenenleri kaldırmak için önceki dizenin aynı alfabe ile bitip bitmediğini kontrol edin (neden? - egzersiz)

public static void main(String[] args) {

    for (String str : permStr("ABBB")){
        System.out.println(str);
    }
}

static Vector<String> permStr(String str){

    if (str.length() == 1){
        Vector<String> ret = new Vector<String>();
        ret.add(str);
        return ret;
    }

    char start = str.charAt(0);
    Vector<String> endStrs = permStr(str.substring(1));
    Vector<String> newEndStrs = new Vector<String>();
    for (String endStr : endStrs){
        for (int j = 0; j <= endStr.length(); j++){
            if (endStr.substring(0, j).endsWith(String.valueOf(start)))
                break;
            newEndStrs.add(endStr.substring(0, j) + String.valueOf(start) + endStr.substring(j));
        }
    }
    return newEndStrs;
}

Tüm permütasyonları ve kopyaları yazdırır


8

C ++ 'da özyinelemeli çözüm

int main (int argc, char * const argv[]) {
        string s = "sarp";
        bool used [4];
        permute(0, "", used, s);
}

void permute(int level, string permuted, bool used [], string &original) {
    int length = original.length();

    if(level == length) { // permutation complete, display
        cout << permuted << endl;
    } else {
        for(int i=0; i<length; i++) { // try to add an unused character
            if(!used[i]) {
                used[i] = true;
                permute(level+1, original[i] + permuted, used, original); // find the permutations starting with this string
                used[i] = false;
            }
        }
}

7

Perl'de, kendinizi küçük harfli alfabe ile sınırlamak istiyorsanız, bunu yapabilirsiniz:

my @result = ("a" .. "zzzz");

Bu, küçük harfler kullanarak 1 ile 4 karakter arasındaki tüm olası dizeleri verir. Büyük harf "a"için "A"ve "zzzz"olarak değiştirin "ZZZZ".

Karışık durumda, çok daha zorlaşır ve muhtemelen Perl'in böyle yerleşik operatörlerinden biriyle yapılamaz.


7

Yakut işe yarayan cevap:

class String
  def each_char_with_index
    0.upto(size - 1) do |index|
      yield(self[index..index], index)
    end
  end
  def remove_char_at(index)
    return self[1..-1] if index == 0
    self[0..(index-1)] + self[(index+1)..-1]
  end
end

def permute(str, prefix = '')
  if str.size == 0
    puts prefix
    return
  end
  str.each_char_with_index do |char, index|
    permute(str.remove_char_at(index), prefix + char)
  end
end

# example
# permute("abc")

Ruby'de süslü bir astar için: stackoverflow.com/questions/5773961/…
dojosto

6
import java.util.*;

public class all_subsets {
    public static void main(String[] args) {
        String a = "abcd";
        for(String s: all_perm(a)) {
            System.out.println(s);
        }
    }

    public static Set<String> concat(String c, Set<String> lst) {
        HashSet<String> ret_set = new HashSet<String>();
        for(String s: lst) {
            ret_set.add(c+s);
        }
        return ret_set;
    }

    public static HashSet<String> all_perm(String a) {
        HashSet<String> set = new HashSet<String>();
        if(a.length() == 1) {
            set.add(a);
        } else {
            for(int i=0; i<a.length(); i++) {
                set.addAll(concat(a.charAt(i)+"", all_perm(a.substring(0, i)+a.substring(i+1, a.length()))));
            }
        }
        return set;
    }
}

6

Aşağıdaki Java özyinelemesi, belirli bir dizenin tüm permütasyonlarını yazdırır:

//call it as permut("",str);

public void permut(String str1,String str2){
    if(str2.length() != 0){
        char ch = str2.charAt(0);
        for(int i = 0; i <= str1.length();i++)
            permut(str1.substring(0,i) + ch + str1.substring(i,str1.length()),
                     str2.substring(1,str2.length()));
    }else{
    System.out.println(str1);
    }
}

Aşağıda n yapar "permut" yönteminin güncellenmiş sürümü aşağıdadır! (n faktöryel) yukarıdaki yönteme kıyasla daha az özyinelemeli çağrı

//call it as permut("",str);

public void permut(String str1,String str2){
   if(str2.length() > 1){
       char ch = str2.charAt(0);
       for(int i = 0; i <= str1.length();i++)
          permut(str1.substring(0,i) + ch + str1.substring(i,str1.length()),
                 str2.substring(1,str2.length()));
   }else{
    char ch = str2.charAt(0);
    for(int i = 0; i <= str1.length();i++)
        System.out.println(str1.substring(0,i) + ch +    str1.substring(i,str1.length()),
                 str2.substring(1,str2.length()));
   }
}

Bu en temiz çözüm ve daha önce "Kodlama Röportajını Kırma" kitabında gördüğüme inanıyorum
Tao Zhang

1
@TaoZhang tamamlayıcı için teşekkürler, ben herhangi bir yerden kopyalamadı ancak birisi benzer algo yaratmış olabilir. Neyse daha az özyinelemeli aramalar için yukarıdaki kodu güncelledim
Ramy

5

Bunu ilk etapta neden yapmak isteyeceğinizden emin değilim. Orta derecede büyük x ve y değerleri için sonuç kümesi büyük olacaktır ve x ve / veya y büyüdükçe katlanarak büyüyecektir.

Diyelim ki, olası karakter kümeniz alfabenin 26 küçük harfidir ve uygulamanızdan uzunluk = 5 olan tüm permütasyonları üretmesini istersiniz. 5) dizeleri geri. Bu uzunluğu 6'ya kadar çarptığınızda 308.915.776 dizeyi geri alırsınız. Bu sayılar çok çabuk acıyla büyüyor.

İşte Java'da bir araya getirdiğim bir çözüm. İki çalışma zamanı argümanı sağlamanız gerekir (x ve y'ye karşılık gelir). İyi eğlenceler.

public class GeneratePermutations {
    public static void main(String[] args) {
        int lower = Integer.parseInt(args[0]);
        int upper = Integer.parseInt(args[1]);

        if (upper < lower || upper == 0 || lower == 0) {
            System.exit(0);
        }

        for (int length = lower; length <= upper; length++) {
            generate(length, "");
        }
    }

    private static void generate(int length, String partial) {
        if (length <= 0) {
            System.out.println(partial);
        } else {
            for (char c = 'a'; c <= 'z'; c++) {
                generate(length - 1, partial + c);
            }
        }
    }
}

Uzun zaman geçirdin, ama onları tekrarla üretmiyor musun?
Kakira

5

Javascript'te bulduğum özyinelemeli olmayan bir sürüm. Eleman değişiminde bazı benzerliklere sahip olmasına rağmen, Knuth'un yukarıdaki özyinelemesiz olanı temel almaz. 8 öğeye kadar giriş dizileri için doğruluğunu doğruladım.

Hızlı bir optimizasyon outdiziyi önceden uçurur ve bundan kaçınır push().

Temel fikir:

  1. Tek bir kaynak dizisi verildiğinde, ilk öğeyi sırayla her bir öğeyle sırayla değiştiren, her seferinde diğer öğeleri bozulmadan bırakarak yeni bir dizi dizi oluşturun. örneğin: 1234 verildi, 1234, 2134, 3214, 4231 oluşturun.

  2. Önceki geçişteki her diziyi yeni geçiş için tohum olarak kullanın, ancak ilk öğeyi değiştirmek yerine ikinci öğeyi sonraki her öğeyle değiştirin. Ayrıca, bu sefer, orijinal diziyi çıktıya dahil etmeyin.

  3. Tamamlanana kadar 2. adımı tekrarlayın.

İşte kod örneği:

function oxe_perm(src, depth, index)
{
    var perm = src.slice();     // duplicates src.
    perm = perm.split("");
    perm[depth] = src[index];
    perm[index] = src[depth];
    perm = perm.join("");
    return perm;
}

function oxe_permutations(src)
{
    out = new Array();

    out.push(src);

    for (depth = 0; depth < src.length; depth++) {
        var numInPreviousPass = out.length;
        for (var m = 0; m < numInPreviousPass; ++m) {
            for (var n = depth + 1; n < src.length; ++n) {
                out.push(oxe_perm(out[m], depth, n));
            }
        }
    }

    return out;
}

3

Yakutta:

str = "a"
100_000_000.times {puts str.next!}

Oldukça hızlı, ama biraz zaman alacak =). Tabii ki, kısa dizeler sizin için ilginç değilse "aaaaaaaa" başlayabilirsiniz.

Gerçi gerçek soruyu yanlış yorumlamış olabilirim - mesajlardan birinde dizelerin bir bruteforce kütüphanesine ihtiyaç duyuyorsunuz gibi geldi, ancak ana soruda belirli bir dizeye izin vermeniz gerekiyor gibi geliyor.

Sorununuz buna benzer: http://beust.com/weblog/archives/000491.html (basamakların hiçbirinin tekrar etmediği tüm tamsayıları listeleyin, bu da bir çok dili çözdü. ocaml guy permutations ve bazı java guy başka bir çözüm kullanarak).


Teklifinizle ilgili bir sorun şudur: str.next! yazdırılabilir tüm karakterler üzerinde yinelenmez. Örneğiniz yalnızca küçük harfler üretecektir - noktalama işaretleri veya büyük harfler içermez.
Jarsen

3

Bugün buna ihtiyacım vardı ve verilen cevaplar beni doğru yönde göstermesine rağmen, istediğim gibi değildi.

İşte Heap yöntemini kullanan bir uygulama. Dizinin uzunluğu en az 3 olmalıdır ve pratik hususlar için ne yapmak istediğinize, sabrınıza ve saat hızına bağlı olarak 10'dan büyük olmamalıdır.

Eğer döngü, initialise girmeden önce Perm(1 To N), ilk permütasyon ile Stack(3 To N)sıfır ve * ile Levelbirlikte 2**. Döngü çağrısının sonunda, NextPermişimiz bittiğinde false döndürür.

* VB bunu sizin için yapacak.

** Bunu gereksiz kılmak için NextPerm'i biraz değiştirebilirsiniz, ancak bu daha açıktır.

Option Explicit

Function NextPerm(Perm() As Long, Stack() As Long, Level As Long) As Boolean
Dim N As Long
If Level = 2 Then
    Swap Perm(1), Perm(2)
    Level = 3
Else
    While Stack(Level) = Level - 1
        Stack(Level) = 0
        If Level = UBound(Stack) Then Exit Function
        Level = Level + 1
    Wend
    Stack(Level) = Stack(Level) + 1
    If Level And 1 Then N = 1 Else N = Stack(Level)
    Swap Perm(N), Perm(Level)
    Level = 2
End If
NextPerm = True
End Function

Sub Swap(A As Long, B As Long)
A = A Xor B
B = A Xor B
A = A Xor B
End Sub

'This is just for testing.
Private Sub Form_Paint()
Const Max = 8
Dim A(1 To Max) As Long, I As Long
Dim S(3 To Max) As Long, J As Long
Dim Test As New Collection, T As String
For I = 1 To UBound(A)
    A(I) = I
Next
Cls
ScaleLeft = 0
J = 2
Do
    If CurrentY + TextHeight("0") > ScaleHeight Then
        ScaleLeft = ScaleLeft - TextWidth(" 0 ") * (UBound(A) + 1)
        CurrentY = 0
        CurrentX = 0
    End If
    T = vbNullString
    For I = 1 To UBound(A)
        Print A(I);
        T = T & Hex(A(I))
    Next
    Print
    Test.Add Null, T
Loop While NextPerm(A, S, J)
J = 1
For I = 2 To UBound(A)
    J = J * I
Next
If J <> Test.Count Then Stop
End Sub

Diğer yöntemler çeşitli yazarlar tarafından tarif edilmiştir. Knuth iki tanesini tanımlar, biri sözcüksel düzen verir, ancak karmaşık ve yavaştır, diğeri ise basit değişikliklerin yöntemi olarak bilinir. Jie Gao ve Dianjun Wang da ilginç bir makale yazdı.


2

Python'daki bu kod, allowed_charactersset [0,1]ve max maksimum 4 karakterle çağrıldığında 2 ^ 4 sonuç oluşturur:

['0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111']

def generate_permutations(chars = 4) :

#modify if in need!
    allowed_chars = [
        '0',
        '1',
    ]

    status = []
    for tmp in range(chars) :
        status.append(0)

    last_char = len(allowed_chars)

    rows = []
    for x in xrange(last_char ** chars) :
        rows.append("")
        for y in range(chars - 1 , -1, -1) :
            key = status[y]
            rows[x] = allowed_chars[key] + rows[x]

        for pos in range(chars - 1, -1, -1) :
            if(status[pos] == last_char - 1) :
                status[pos] = 0
            else :
                status[pos] += 1
                break;

    return rows

import sys


print generate_permutations()

Umarım bu sizin için yararlıdır. Sadece sayılarla değil, herhangi bir karakterle çalışır


Bu permütasyonlar değil, alt küme seçimidir, yani geçerli bir permütasyon üç karaktere de sahip olmalıdır.
Schultz9999

ah? üzgünüm ne dediğini anlamıyorum. Eğer sabit bir versiyonunu terk düzeltmek, ben topluluk şey wiki edeceğiz
droope


0

Bu, sorunuzu tam olarak cevaplamasa da, aynı uzunlukta birkaç dizeden harflerin her permütasyonunu oluşturmanın bir yolu: örneğin, kelimeleriniz "kahve", "joomla" ve "moodle" ise, "coodle", "joodee", "joffle" vb.

Temel olarak, kombinasyon sayısı gücünün (kelime sayısı) (kelime başına harf sayısı). Bu nedenle, 0 ile kombinasyon sayısı arasında rasgele bir sayı seçin - 1, bu sayıyı tabana (kelime sayısı) dönüştürün, ardından bu sayının her bir basamağını, bir sonraki harfi hangi kelimenin alacağı göstergesi olarak kullanın.

örneğin: yukarıdaki örnekte. 3 kelime, 6 harf = 729 kombinasyon. Rastgele bir sayı seçin: 465. Taban 3'e dönüştürün: 122020. İlk harfi 1, 2, 2, 3, 2, 4., 0 kelimesinden alın ... "joofle" olsun.

Tüm permütasyonları istiyorsanız, sadece 0'dan 728'e kadar döngü yapın. Tabii ki, sadece bir rastgele değer seçerseniz , harflerin üzerinde dolaşmak daha basit ve daha az kafa karıştırıcı bir yol olacaktır. Bu yöntem, tüm permütasyonları istiyorsanız, özyinelemeyi önlemenizi sağlar, ayrıca Math'ları (tm) bildiğiniz gibi görünmenizi sağlar !

Kombinasyon sayısı aşırı ise, bunu bir dizi küçük kelimeye ayırabilir ve sonunda birleştirebilirsiniz.


0

c # yinelemeli:

public List<string> Permutations(char[] chars)
    {
        List<string> words = new List<string>();
        words.Add(chars[0].ToString());
        for (int i = 1; i < chars.Length; ++i)
        {
            int currLen = words.Count;
            for (int j = 0; j < currLen; ++j)
            {
                var w = words[j];
                for (int k = 0; k <= w.Length; ++k)
                {
                    var nstr = w.Insert(k, chars[i].ToString());
                    if (k == 0)
                        words[j] = nstr;
                    else
                        words.Add(nstr);
                }
            }
        }
        return words;
    }

0
def gen( x,y,list): #to generate all strings inserting y at different positions
list = []
list.append( y+x )
for i in range( len(x) ):
    list.append( func(x,0,i) + y + func(x,i+1,len(x)-1) )
return list 

def func( x,i,j ): #returns x[i..j]
z = '' 
for i in range(i,j+1):
    z = z+x[i]
return z 

def perm( x , length , list ): #perm function
if length == 1 : # base case
    list.append( x[len(x)-1] )
    return list 
else:
    lists = perm( x , length-1 ,list )
    lists_temp = lists #temporarily storing the list 
    lists = []
    for i in range( len(lists_temp) ) :
        list_temp = gen(lists_temp[i],x[length-2],lists)
        lists += list_temp 
    return lists

0
def permutation(str)
  posibilities = []
  str.split('').each do |char|
    if posibilities.size == 0
      posibilities[0] = char.downcase
      posibilities[1] = char.upcase
    else
      posibilities_count = posibilities.length
      posibilities = posibilities + posibilities
      posibilities_count.times do |i|
        posibilities[i] += char.downcase
        posibilities[i+posibilities_count] += char.upcase
      end
    end
  end
  posibilities
end

İşte özyinelemeyen bir sürümü almam


0

Pitonik çözüm:

from itertools import permutations
s = 'ABCDEF'
p = [''.join(x) for x in permutations(s)]

0

İşte zarif, özyinelemesiz, O (n!) Bir çözüm:

public static StringBuilder[] permutations(String s) {
        if (s.length() == 0)
            return null;
        int length = fact(s.length());
        StringBuilder[] sb = new StringBuilder[length];
        for (int i = 0; i < length; i++) {
            sb[i] = new StringBuilder();
        }
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            int times = length / (i + 1);
            for (int j = 0; j < times; j++) {
                for (int k = 0; k < length / times; k++) {
                    sb[j * length / times + k].insert(k, ch);
                }
            }
        }
        return sb;
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.