Genereer lijst van alle mogelijke permutaties van een string

stemmen
143

Hoe zou ik over het genereren van een lijst van alle mogelijke permutaties van een string tussen x en y tekens, die een variabele lijst characters.

Elke taal zou werken, maar het moet draagbaar zijn.

De vraag is gesteld op 02/08/2008 om 07:57
bron van user
In andere talen...                            


35 antwoorden

stemmen
67

Er zijn verschillende manieren om dit te doen. Gemeenschappelijke methoden gebruiken terugkeer, memoization, of dynamische programmering. Het basisidee is dat je een lijst van alle snaren van lengte 1 te produceren, dan in elke iteratie, voor alle strings die in de laatste herhaling, voeg die string samengevoegd met elk karakter in de string afzonderlijk. (De variabele index in de onderstaande code houdt het begin van de vorige en de volgende iteratie)

Enkele pseudocode:

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)

je zou dan moeten alle strings minder dan x te verwijderen in de lengte, zullen ze de eerste (x-1) * len (originalString) vermeldingen in de lijst zijn.

antwoordde op 02/08/2008 om 08:48
bron van user

stemmen
8

Ranselde ik alleen deze snel omhoog in Ruby:

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

Je zou kunnen kijken naar taal API voor inbouw in type permutatie functies, en je zou in staat zijn om meer geoptimaliseerde code te schrijven, maar als de nummers zijn allemaal zo hoog, ik ben niet zeker dat er veel van een manier om het hebben van veel van de resultaten .

Anyways, het idee achter de code begint met een touwtje met een lengte van 0, dan bijhouden van alle snaren van lengte Z, waarin Z is de huidige omvang in de iteratie. Dan, ga door elke snaar en voeg elk personage op elke snaar. Tenslotte aan het einde, verwijder die onder de x drempel waren en geeft het resultaat.

Ik heb het niet getest met mogelijk betekenisloze ingang (null karakterlijst, bizar waarden van x en y, etc).

antwoordde op 02/08/2008 om 08:56
bron van user

stemmen
4

Ik weet niet zeker waarom je zou willen om dit te doen in de eerste plaats. De resulterende set voor een redelijk grote waarden van x en y zal enorm zijn, en zal exponentieel groeien als x en / of y groter worden.

Laten we zeggen dat uw set van mogelijke tekens is de 26 kleine letters van het alfabet, en u uw toepassing vragen om alle permutaties waarin lengte = 5. Ervan uitgaande dat u niet opraken van het geheugen te genereren krijg je 11.881.376 (dat wil zeggen 26 tot de macht van 5) strings terug. Bump die lengte tot 6, en u zult 308.915.776 strings terug te krijgen. Deze nummers krijgen pijnlijk grote, zeer snel.

Hier is een oplossing die ik in elkaar gezet in Java. Je moet twee runtime argumenten (overeenkomend met x en y) te bieden. Veel plezier.

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);
            }
        }
    }
}
antwoordde op 02/08/2008 om 10:40
bron van user

stemmen
24

Je gaat veel strings te krijgen, dat is zeker ...

\ sum_ {i = x ^ y} {\ frac {r!} {{(ri)}!}} http://www.codecogs.com/eq.latex?%5Csum_%7Bi=x%7D%5Ey% 20% 7B% 20% 5Cfrac% 7BR% 7D% 7B% 7B (ri)% 7D% 7D% 20% 7D!
Wanneer x en y is de manier waarop je ze definiëren en r is het aantal tekens we selecteren uit - -Als ik u goed te begrijpen. Je moet zeker deze te genereren als dat nodig is en niet slordig te krijgen en zeggen, het genereren van een PowerSet en vervolgens filteren de lengte van de snaren.

De volgende is zeker niet de beste manier om deze te genereren, maar het is een interessante terzijde, toch aanzienlijk minder.

Knuth (volume 4, fascicle 2, 7.2.1.3) vertelt ons dat (s, t) -samenstellen komt overeen met s + 1 t dingen die tegelijk met herhaling - een (s, t) -samenstellen notatie wordt gebruikt Knuth dat gelijk is {t \ kiezen {s + t} http://www.codecogs.com/eq.latex?%7Bt%20%5Cchoose%20%7Bs+t%7D%7D . We kunnen dit uit door eerst elke (s, t) -samenstellen in binaire vorm genereren (dus lengte (s + t)) en het tellen van het aantal 0 aan de linkerkant van elk 1.

10001000011101 -> wordt de permutatie: {0, 3, 4, 4, 4, 1}

antwoordde op 05/08/2008 om 05:57
bron van user

stemmen
2

In ruby:

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

Het is vrij snel, maar het gaat om wat tijd in beslag nemen =). Natuurlijk, kunt u beginnen bij "aaaaaaaa" als de korte strings zijn niet interessant voor u.

Ik zou de eigenlijke vraag al hebben verkeerd geïnterpreteerd - in één van de posten het klonk alsof je gewoon behoefte aan een bruteforce bibliotheek van strings, maar in de belangrijkste vraag het klinkt alsof je nodig hebt om een ​​bepaalde reeks permuteren.

Uw probleem is enigszins vergelijkbaar met deze: http://beust.com/weblog/archives/000491.html (een lijst van alle gehele getallen waar geen van de cijfers zich herhalen, wat resulteerde in een heleboel talen het oplossen ervan, met de ocaml man met behulp permutaties en sommige java vent gebruikt nog een andere oplossing).

antwoordde op 15/09/2008 om 18:32
bron van user

stemmen
7

Dit is een vertaling van Mike's Ruby versie, in Common Lisp:

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

En een andere versie, iets korter en het gebruik van meer lusfaciliteit features:

(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)))))
antwoordde op 16/09/2008 om 06:15
bron van user

stemmen
0

Hoewel dit uw vraag niet precies te beantwoorden, hier is een manier om elke permutatie van de letters te genereren uit een aantal snaren van dezelfde lengte: bijvoorbeeld, als uw woorden waren "koffie", "joomla" en "moodle", kunt u verwachten uitgang als "coodle", "joodee", "joffle", etc.

In principe is het aantal combinaties is de (aantal woorden) tot de macht (aantal letters per woord). Dus, kies een willekeurig getal tussen 0 en het aantal combinaties - 1, om te zetten dat dit aantal base (aantal woorden), gebruik dan elk cijfer van dat nummer als de indicator voor welk woord naar de volgende letter uit te nemen.

Bijvoorbeeld: in het bovenstaande voorbeeld. 3 woorden, letters 6 = 729 combinaties. Kies een willekeurig getal: 465. Omzetten naar baseren 3: 122020. Neem de eerste letter van woord 1, 2e van woord 2, 3 uit woord 2, 4 van het woord 0 ... en je krijgt ... "joofle".

Als u alle permutaties, net loop van 0 tot 728. Natuurlijk wilde, als je gewoon op het kiezen van een willekeurige waarde, een veel eenvoudiger minder verwarrende manier zou zijn om lus over de letters. Met deze methode kunt u voorkomen dat terugkeer, moet u wilt dat alle permutaties, plus het maakt je ziet eruit alsof je weet dat wiskunde (tm) !

Als het aantal combinaties is overdreven, kunt u deze opsplitsen in een reeks kleinere woorden aaneen te rijgen aan het eind.

antwoordde op 16/09/2008 om 06:33
bron van user

stemmen
7

Recursieve oplossing in C ++

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;
            }
        }
}
antwoordde op 29/09/2008 om 02:34
bron van user

stemmen
7

Hier is een eenvoudig woord C # recursieve oplossing:

Methode:

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;
        }

Roeping:

string[] letters = new string[]{"a","b","c"};
ArrayList words = CalculateWordPermutations(letters, new ArrayList(), 0);
antwoordde op 20/10/2008 om 01:17
bron van user

stemmen
12

Je zou kunnen kijken naar " Efficiënt Het opsommen van de subsets van een set ", die een algoritme om een deel van wat je wilt doen beschrijft - snel alle subgroepen van N personages uit lengte x genereren y. Het bevat een implementatie in C.

Voor elke subset, zou je nog steeds aan alle permutaties te genereren. Bijvoorbeeld als je wilde 3 personages uit "abcde", dit algoritme geef je aan "abc", "abd", "abe" ... maar je zou moeten ieder naar "ACB", "bac" get permuteren, "BCA", etc.

antwoordde op 14/11/2008 om 20:36
bron van user

stemmen
7

In Perl, als je wilt om jezelf te beperken tot de kleine letters, kunt u dit doen:

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

Dit geeft alle mogelijke strings tussen 1 en 4 tekens met kleine letters. Voor hoofdletters, wijzigen "a"om "A"en "zzzz"om "ZZZZ".

Voor mixed-case wordt het veel moeilijker, en waarschijnlijk niet uitvoerbaar met één van de ingebouwde operatoren Perl als dat.

antwoordde op 15/02/2009 om 11:02
bron van user

stemmen
12

Sommige werken Java-code op basis van antwoord Sarp's :

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);
    }
}
antwoordde op 04/04/2010 om 19:18
bron van user

stemmen
12

Hier is een eenvoudige oplossing in C #.

Genereert alleen de verschillende permutaties van een bepaalde tekenreeks.

    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;
        }
    }
antwoordde op 05/07/2010 om 10:06
bron van user

stemmen
5
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;
    }
}
antwoordde op 24/10/2010 om 23:01
bron van user

stemmen
14

Niet recursieve oplossing volgens Knuth, Python voorbeeld:

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)
antwoordde op 09/11/2010 om 14:58
bron van user

stemmen
7

... en hier is de C-versie:

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;
}
antwoordde op 07/02/2011 om 22:56
bron van user

stemmen
7

permuteren (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 * )] voor duplicaten bij het inbrengen elk schrift gecontroleerd of eerdere tekenreeks eindigt met hetzelfde alfabet (waarom? -Oefening)

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;
}

Drukt alle permutaties sans duplicaten

antwoordde op 22/02/2011 om 19:45
bron van user

stemmen
2

Deze code in python, als ze worden opgeroepen met de allowed_charactersset aan [0,1]en karakter max 4, zou het genereren van 2 ^ 4 resultaten:

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

Hoop dat dit nuttig is voor jou. Werkt met een willekeurig karakter, niet alleen cijfers

antwoordde op 26/05/2011 om 15:22
bron van user

stemmen
5

Hier is een niet-recursieve versie die ik kwam met, in javascript. Het is niet gebaseerd op niet-recursieve een Knuth hierboven, hoewel het aantal overeenkomsten in element wisselen. Ik heb haar juistheid gecontroleerd voor input arrays van maximaal 8 elementen.

Een snelle optimalisatie zou vooraf worden flighting de outarray en het vermijden push().

Het basisidee is:

  1. Die een enkele bronmatrix genereren van een eerste nieuwe set arrays waarvan het eerste element wisselen elk volgend element beurtelings telkens terwijl de andere elementen onverstoord. bijvoorbeeld: aangezien 1234, het genereren van 1234, 2134, 3214, 4231.

  2. Met elke reeks van de voorgaande doorgang als de kiem voor een nieuwe pas, maar in plaats van ruilen het eerste element het tweede element verwisselen bij elke volgende element. Ook deze keer zijn exclusief de oorspronkelijke array in de uitvoer.

  3. Herhaal stap 2 tot ze gaar zijn.

Hier is de code voorbeeld:

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;
}
antwoordde op 03/08/2011 om 08:11
bron van user

stemmen
3

Ik moest dit vandaag, en hoewel de antwoorden al gegeven me wees in de goede richting, ze waren niet helemaal wat ik wilde.

Hier is een implementatie met behulp van Heap's methode. De lengte van de array moet minimaal 3 en uit praktische overwegingen niet groter zijn dan 10 of zo, afhankelijk van wat je wilt doen, geduld en kloksnelheid.

Voordat u uw loop te voeren, initialiseren Perm(1 To N)met het eerste permutatie, Stack(3 To N)met nullen *, en Levelmet 2**. Aan het einde van de lus oproep NextPerm, die zal return false als we klaar zijn.

* VB zal dat voor je doen.

** U kunt NextPerm een ​​beetje om dit overbodig te maken te veranderen, maar het is duidelijker als dit.

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

Andere methoden worden beschreven door verschillende auteurs. Knuth beschrijft twee, geeft men lexicale rangorde, maar is complex en traag, de andere is bekend als de methode van gewone veranderingen. Jie Gao en Dianjun Wang schreef ook een interessant papier.

antwoordde op 02/10/2011 om 10:13
bron van user

stemmen
35

Het is beter om backtracking te gebruiken

#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;
}
antwoordde op 10/01/2012 om 19:00
bron van user

stemmen
7

Ruby antwoord dat werkt:

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")
antwoordde op 20/04/2012 om 01:21
bron van user

stemmen
0

c # iteratief:

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;
    }
antwoordde op 26/07/2012 om 16:20
bron van user

stemmen
0

Er is een iteratief Java-implementatie in UncommonsMaths (werkt voor een lijst van objecten):

/**
 * Generate the indices into the elements array for the next permutation. The
 * algorithm is from Kenneth H. Rosen, Discrete Mathematics and its 
 * Applications, 2nd edition (NY: McGraw-Hill, 1991), p. 284)
 */
private void generateNextPermutationIndices()
{
    if (remainingPermutations == 0)
    {
        throw new IllegalStateException("There are no permutations " +
             "remaining. Generator must be reset to continue using.");
    }
    else if (remainingPermutations < totalPermutations)
    {
        // Find largest index j with 
        // permutationIndices[j] < permutationIndices[j + 1]
        int j = permutationIndices.length - 2;
        while (permutationIndices[j] > permutationIndices[j + 1])
        {
            j--;
        }

        // Find index k such that permutationIndices[k] is smallest integer 
        // greater than permutationIndices[j] to the right
        // of permutationIndices[j].
        int k = permutationIndices.length - 1;
        while (permutationIndices[j] > permutationIndices[k])
        {
            k--;
        }

        // Interchange permutation indices.
        int temp = permutationIndices[k];
        permutationIndices[k] = permutationIndices[j];
        permutationIndices[j] = temp;

        // Put tail end of permutation after jth position in increasing order.
        int r = permutationIndices.length - 1;
        int s = j + 1;

        while (r > s)
        {
            temp = permutationIndices[s];
            permutationIndices[s] = permutationIndices[r];
            permutationIndices[r] = temp;
            r--;
            s++;
        }
    }
    --remainingPermutations;
}

/**
 * Generate the next permutation and return a list containing
 * the elements in the appropriate order.  This overloaded method
 * allows the caller to provide a list that will be used and returned.
 * The purpose of this is to improve performance when iterating over
 * permutations.  If the {@link #nextPermutationAsList()} method is
 * used it will create a new list every time.  When iterating over
 * permutations this will result in lots of short-lived objects that
 * have to be garbage collected.  This method allows a single list
 * instance to be reused in such circumstances.
 * @param destination Provides a list to use to create the
 * permutation.  This is the list that will be returned, once
 * it has been filled with the elements in the appropriate order.
 * @return The next permutation as a list.
 */
public List<T> nextPermutationAsList(List<T> destination)
{
    generateNextPermutationIndices();
    // Generate actual permutation.
    destination.clear();
    for (int i : permutationIndices)
    {
        destination.add(elements[i]);
    }
    return destination;
}

volledige bron

antwoordde op 07/05/2013 om 02:18
bron van user

stemmen
6

De volgende Java recursie drukt alle permutaties van een bepaalde string:

//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);
    }
}

Hieronder vindt u de bijgewerkte versie van above "PERMUT" methode die n maakt! (N Factoriële) minder recursieve aanroepen vergelijking met de bovengenoemde werkwijze

//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()));
   }
}
antwoordde op 19/06/2013 om 05:23
bron van user

stemmen
0

Een recursieve oplossing python. Het goede van deze code is dat het exporteert een woordenboek, met sleutels als strings en alle mogelijke permutaties als waarden. Alle mogelijke snaarlengten zijn inbegrepen, dus in feite, maakt u een superset.

Als je alleen nodig de uiteindelijke permutaties, kunt u andere sleutels uit het woordenboek te verwijderen.

In deze code, het woordenboek van permutaties is wereldwijd.

Aan de basis geval, ik bewaar de waarde als beide mogelijkheden in een lijst. perms['ab'] = ['ab','ba'].

Voor hogere snaarlengten de functie betreft snaarlengten lager en bevat de eerder berekende permutaties.

De functie doet twee dingen:

  • noemt zichzelf met een kleinere reeks
  • geeft een lijst met permutaties van een bepaalde reeks indien reeds beschikbaar is. Als terug naar zichzelf, zullen deze worden gebruikt om toe te voegen aan het karakter en het creëren van nieuwere permutaties.

Duur voor het geheugen.

perms = {}
def perm(input_string):
    global perms
    if input_string in perms:
        return perms[input_string] # This will send a list of all permutations
    elif len(input_string) == 2:
        perms[input_string] = [input_string, input_string[-1] + input_string [-2]]
        return perms[input_string]
    else:
        perms[input_string] = []
        for index in range(0, len(input_string)):
            new_string = input_string[0:index] + input_string[index +1:]
            perm(new_string)
            for entries in perms[new_string]:
                perms[input_string].append(input_string[index] + entries)
    return perms[input_string]
antwoordde op 05/07/2013 om 05:15
bron van user

stemmen
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
antwoordde op 22/08/2013 om 18:51
bron van user

stemmen
0

Recursieve Solution met chauffeur main()methode.

public class AllPermutationsOfString {
public static void stringPermutations(String newstring, String remaining) {
    if(remaining.length()==0)
        System.out.println(newstring);

    for(int i=0; i<remaining.length(); i++) {
        String newRemaining = remaining.replaceFirst(remaining.charAt(i)+"", "");
        stringPermutations(newstring+remaining.charAt(i), newRemaining);
    }
}

public static void main(String[] args) {
    String string = "abc";
    AllPermutationsOfString.stringPermutations("", string); 
}

}

antwoordde op 19/10/2013 om 02:34
bron van user

stemmen
12

Er zijn veel goede antwoorden. Ik stel ook voor een zeer eenvoudige recursieve oplossing in C ++.

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

Opmerking : snaren met herhaalde tekens zal geen unieke permutaties.

antwoordde op 08/01/2014 om 12:00
bron van user

stemmen
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

Hier is mijn nemen op een niet recursieve versie

antwoordde op 23/01/2014 om 04:28
bron van user

stemmen
2

Hier is een link die beschrijft hoe permutaties van een string af te drukken. http://nipun-linuxtips.blogspot.in/2012/11/print-all-permutations-of-characters-in.html

antwoordde op 13/02/2014 om 22:08
bron van user

stemmen
0

De pythonic oplossing:

from itertools import permutations
s = 'ABCDEF'
p = [''.join(x) for x in permutations(s)]
antwoordde op 13/07/2014 om 08:51
bron van user

stemmen
0

Nou hier is een elegante, niet-recursieve, O (n!) Oplossing:

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;
    }
antwoordde op 27/06/2015 om 08:44
bron van user

stemmen
0

code geschreven voor Java-taal:

namo.algorithms pakket;

import java.util.Scanner;

public class Permuations {

public static int totalPermutationsCount = 0;
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        System.out.println("input string : ");
        String inputString = sc.nextLine();
        System.out.println("given input String ==> "+inputString+ " :: length is = "+inputString.length());
        findPermuationsOfString(-1, inputString);
        System.out.println("**************************************");
        System.out.println("total permutation strings ==> "+totalPermutationsCount);
    }


    public  static void findPermuationsOfString(int fixedIndex, String inputString) {
        int currentIndex = fixedIndex +1;

        for (int i = currentIndex; i < inputString.length(); i++) {
            //swap elements and call the findPermuationsOfString()

            char[] carr = inputString.toCharArray();
            char tmp = carr[currentIndex];
            carr[currentIndex] = carr[i];
            carr[i] = tmp;
            inputString =  new String(carr);

            //System.out.println("chat At : current String ==> "+inputString.charAt(currentIndex));
            if(currentIndex == inputString.length()-1) {
                totalPermutationsCount++;
                System.out.println("permuation string ==> "+inputString);
            } else {
                //System.out.println("in else block>>>>");
                findPermuationsOfString(currentIndex, inputString);
                 char[] rarr = inputString.toCharArray();
                    char rtmp = carr[i];
                    carr[i] = carr[currentIndex];
                    carr[currentIndex] = rtmp;
                    inputString =  new String(carr);
            }
        }
    }

}

antwoordde op 05/06/2016 om 08:42
bron van user

stemmen
0

De mogelijke permutaties tekenreeks kan worden berekend met behulp recursieve functie. Hieronder is een van de mogelijke oplossing.

public static String insertCharAt(String s, int index, char c) {
        StringBuffer sb = new StringBuffer(s);
        StringBuffer sbb = sb.insert(index, c);
        return sbb.toString();
}

public static ArrayList<String> getPerm(String s, int index) {
        ArrayList<String> perm = new ArrayList<String>();

        if (index == s.length()-1) {
            perm.add(String.valueOf(s.charAt(index)));
            return perm;
        }

        ArrayList<String> p = getPerm(s, index+1);
        char c = s.charAt(index);

        for(String pp : p) {
            for (int idx=0; idx<pp.length()+1; idx++) {
                String ss = insertCharAt(pp, idx, c);
                perm.add(ss);
            }
        }

        return perm;    
}

public static void testGetPerm(String s) {
        ArrayList<String> perm = getPerm(s,0);
        System.out.println(s+" --> total permutation are :: "+perm.size());
        System.out.println(perm.toString());
}
antwoordde op 06/02/2017 om 06:00
bron van user

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more