Menghasilkan semua permutasi dari string yang diberikan

418

Apa cara yang elegan untuk menemukan semua permutasi string. Misalnya permutasi untuk ba, akan badan ab, tetapi bagaimana dengan string yang lebih panjang seperti abcdefgh? Apakah ada contoh implementasi Java?

GurdeepS
sumber
3
Ada banyak jawaban di sini: stackoverflow.com/questions/361/…
Marek Sapota
ini adalah pertanyaan yang sangat populer. Anda dapat melihatnya di sini: careercup.com/question?id=3861299
JJunior
9
Ada asumsi yang perlu disebutkan. Karakternya unik. Misalnya, untuk String "aaaa" hanya ada satu jawaban. Untuk mendapatkan jawaban yang lebih umum, Anda dapat menyimpan string dalam satu set untuk menghindari duplikasi
Afshin Moazami
1
Apakah pengulangan karakter diperbolehkan, atau pengulangan karakter tidak diperbolehkan? Bisakah satu string memiliki beberapa kejadian dengan karakter yang sama?
Anderson Green
2
Baca teorinya (atau jika, seperti saya, Anda malas, buka en.wikipedia.org/wiki/Permutation ) dan terapkan algoritma yang nyata. Pada dasarnya Anda dapat membuat urutan urutan elemen (fakta bahwa string tidak relevan) dan berjalan melalui urutan sampai Anda kembali ke awal. Hindari segala sesuatu yang melibatkan rekursi atau manipulasi string.
CurtainDog

Jawaban:

601
public static void permutation(String str) { 
    permutation("", str); 
}

private static void permutation(String prefix, String str) {
    int n = str.length();
    if (n == 0) System.out.println(prefix);
    else {
        for (int i = 0; i < n; i++)
            permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i+1, n));
    }
}

(melalui Pengantar Pemrograman di Jawa )

SuperJulietta
sumber
67
Solusi tampaknya datang dari sini introcs.cs.princeton.edu/java/23recursion/…
cyber-monk
48
Itu bukan ilmu roket, saya datang dengan jawaban yang hampir sama. Tweak kecil: alih-alih berulang sampai n==0, Anda dapat menghentikan level sebelumnya pada n==1dan mencetak prefix + str.
lambshaanxy
7
"Apa kompleksitas waktu dan ruang dari ini?" tanpa semacam jawaban parsial caching algoritma apa pun yang menghasilkan permutasi adalah o (n!) karena hasil yang ditetapkan untuk pertanyaan permutasi adalah faktorial untuk input.
jeremyjjbrown
9
Elegan, ya. Tetapi solusi yang mengkonversi ke array char dan swap untuk menghasilkan permutasi akan membutuhkan lebih sedikit menyalin dan menghasilkan lebih sedikit sampah. Algoritma ini juga gagal memperhitungkan karakter yang berulang.
Gene
20
@AfshinMoazami saya pikir str.substring (i +1, n) dapat diganti dengan str.substring (i +1). Menggunakan str.substring (i) akan menyebabkan java.lang.StackOverflowError.
Ayusman
196

Gunakan rekursi.

  • Coba masing-masing huruf pada gilirannya sebagai huruf pertama dan kemudian temukan semua permutasi dari huruf yang tersisa menggunakan panggilan rekursif.
  • Kasus dasar adalah ketika input adalah string kosong, satu-satunya permutasi adalah string kosong.
Mark Byers
sumber
3
Bagaimana Anda bisa menambahkan tipe kembali ke metode permute? kompiler tidak dapat menentukan tipe kembalinya metode ini di setiap iterasi, meskipun itu jelas merupakan tipe String.
user1712095
Bagaimana Anda memastikan permutasi yang berbeda dalam metode ini?
kapad
70

Inilah solusi saya yang didasarkan pada gagasan buku "Cracking the Coding Wawancara" (P54):

/**
 * List permutations of a string.
 * 
 * @param s the input string
 * @return  the list of permutations
 */
public static ArrayList<String> permutation(String s) {
    // The result
    ArrayList<String> res = new ArrayList<String>();
    // If input string's length is 1, return {s}
    if (s.length() == 1) {
        res.add(s);
    } else if (s.length() > 1) {
        int lastIndex = s.length() - 1;
        // Find out the last character
        String last = s.substring(lastIndex);
        // Rest of the string
        String rest = s.substring(0, lastIndex);
        // Perform permutation on the rest string and
        // merge with the last character
        res = merge(permutation(rest), last);
    }
    return res;
}

/**
 * @param list a result of permutation, e.g. {"ab", "ba"}
 * @param c    the last character
 * @return     a merged new list, e.g. {"cab", "acb" ... }
 */
public static ArrayList<String> merge(ArrayList<String> list, String c) {
    ArrayList<String> res = new ArrayList<>();
    // Loop through all the string in the list
    for (String s : list) {
        // For each string, insert the last character to all possible positions
        // and add them to the new list
        for (int i = 0; i <= s.length(); ++i) {
            String ps = new StringBuffer(s).insert(i, c).toString();
            res.add(ps);
        }
    }
    return res;
}

Menjalankan output dari string "abcd":

  • Langkah 1: Gabungkan [a] dan b: [ba, ab]

  • Langkah 2: Gabungkan [ba, ab] dan c: [cba, bca, bac, cab, acb, abc]

  • Langkah 3: Gabungkan [cba, bca, bac, cab, acb, abc] dan d: [dcba, cdba, cbda, cbad, dbca, bdca, bcda, bcad, dbac, bdac, badc, bacd, dcab, cdab, cadb , cabd, dacb, adcb, acdb, acbd, dabc, adbc, abdc, abcd]

jeantimex
sumber
Halaman (71) dalam Cracking the Coding Wawancara Buku, Edisi 6. :)
KarimIhab
5
Apakah ini benar-benar solusi yang baik? Itu bergantung pada menyimpan hasil dalam daftar, oleh karena itu untuk string input pendek itu tumbuh di luar kendali.
Androrider
apa yang dilakukan merger?
Basavaraj Walikar
Ini memasukkan c di setiap posisi yang mungkin dari setiap string dalam daftar jadi jika daftar hanya berisi ["b"] dan c adalah "a" hasil penggabungan adalah ["ab", "ba"] di sini solusi yang sama dengan Swift gist.github. com / daniaDlbani / 3bc10e02541f9ba310d546040c5322fc
Dania Delbani
53

Dari semua solusi yang diberikan di sini dan di forum lain, saya paling suka Mark Byers. Deskripsi itu sebenarnya membuat saya berpikir dan mengkodekannya sendiri. Sayang sekali saya tidak bisa memilih solusinya karena saya pemula.
Bagaimanapun di sini adalah implementasi dari deskripsinya

public class PermTest {

    public static void main(String[] args) throws Exception {
        String str = "abcdef";
        StringBuffer strBuf = new StringBuffer(str);
        doPerm(strBuf,0);
    }

    private static void doPerm(StringBuffer str, int index){

        if(index == str.length())
            System.out.println(str);            
        else { //recursively solve this by placing all other chars at current first pos
            doPerm(str, index+1);
            for (int i = index+1; i < str.length(); i++) {//start swapping all other chars with current first char
                swap(str,index, i);
                doPerm(str, index+1);
                swap(str,i, index);//restore back my string buffer
            }
        }
    }

    private  static void swap(StringBuffer str, int pos1, int pos2){
        char t1 = str.charAt(pos1);
        str.setCharAt(pos1, str.charAt(pos2));
        str.setCharAt(pos2, t1);
    }
}   

Saya lebih suka solusi ini daripada yang pertama di utas ini karena solusi ini menggunakan StringBuffer. Saya tidak akan mengatakan solusi saya tidak membuat string sementara (itu sebenarnya tidak di system.out.printlnmana toString()StringBuffer dipanggil). Tapi saya hanya merasa ini lebih baik daripada solusi pertama di mana terlalu banyak string literal dibuat. Mungkin ada orang kinerja di luar sana yang dapat mengevaluasi ini dalam hal 'memori' (untuk 'waktu' itu sudah terlambat karena 'swap' tambahan)

srikanth yaradla
sumber
Mengapa tidak hanya melakukan if(index == str.length())dan doPerm(str, index + 1);? The currPostampaknya tidak perlu di sini.
Robur_131
Maaf, bisakah Anda menjelaskan lebih lanjut tentang pertanyaan itu? Apakah Anda hanya menyarankan untuk tidak menggunakan variabel arus ekstra (digunakan karena beberapa kejadian dan juga keterbacaan) jika tidak silakan tempelkan solusi yang Anda sarankan untuk melihat
srikanth yaradla
Ah saya mengerti maksud Anda adalah perubahan pada kondisi dasar dengan pengindeksan ke depan. Bekerja dengan baik. Hanya saja solusi yang saya sajikan sebagian besar dipengaruhi oleh kemudian solusi lain yang sering melewati string terpotong daripada yang asli (yang mana 0 masuk akal). Namun demikian terima kasih telah menunjuk. Akan melihat apakah saya dapat mengedit, sudah bertahun-tahun sejak saya masuk ke situs ini.
srikanth yaradla
22

Solusi yang sangat mendasar di Jawa adalah dengan menggunakan rekursi + Set (untuk menghindari pengulangan) jika Anda ingin menyimpan dan mengembalikan string solusi:

public static Set<String> generatePerm(String input)
{
    Set<String> set = new HashSet<String>();
    if (input == "")
        return set;

    Character a = input.charAt(0);

    if (input.length() > 1)
    {
        input = input.substring(1);

        Set<String> permSet = generatePerm(input);

        for (String x : permSet)
        {
            for (int i = 0; i <= x.length(); i++)
            {
                set.add(x.substring(0, i) + a + x.substring(i));
            }
        }
    }
    else
    {
        set.add(a + "");
    }
    return set;
}
penghancur
sumber
2
Apa kompleksitas waktu dari alogrithm ini ??
ashisahu
1
@ashisahu O (n!) karena kita punya n! permutasi dalam string n panjang yang diberikan.
Zok
17

Semua kontributor sebelumnya telah melakukan pekerjaan yang hebat menjelaskan dan menyediakan kode. Saya pikir saya harus membagikan pendekatan ini juga karena mungkin membantu seseorang juga. Solusinya didasarkan pada ( algoritma heaps ' )

Beberapa barang:

  1. Perhatikan item terakhir yang digambarkan dalam excel hanya untuk membantu Anda memvisualisasikan logika dengan lebih baik. Jadi, nilai aktual pada kolom terakhir adalah 2,1,0 (jika kita menjalankan kode karena kita berurusan dengan array dan array mulai dengan 0).

  2. Algoritma swapping terjadi berdasarkan nilai genap atau ganjil dari posisi saat ini. Ini sangat jelas jika Anda melihat di mana metode swap dipanggil. Anda dapat melihat apa yang terjadi.

Inilah yang terjadi: masukkan deskripsi gambar di sini

public static void main(String[] args) {

        String ourword = "abc";
        String[] ourArray = ourword.split("");
        permute(ourArray, ourArray.length);

    }

    private static void swap(String[] ourarray, int right, int left) {
        String temp = ourarray[right];
        ourarray[right] = ourarray[left];
        ourarray[left] = temp;
    }

    public static void permute(String[] ourArray, int currentPosition) {
        if (currentPosition == 1) {
            System.out.println(Arrays.toString(ourArray));
        } else {
            for (int i = 0; i < currentPosition; i++) {
                // subtract one from the last position (here is where you are
                // selecting the the next last item 
                permute(ourArray, currentPosition - 1);

                // if it's odd position
                if (currentPosition % 2 == 1) {
                    swap(ourArray, 0, currentPosition - 1);
                } else {
                    swap(ourArray, i, currentPosition - 1);
                }
            }
        }
    }
grepit
sumber
11

Yang ini tanpa rekursi

public static void permute(String s) {
    if(null==s || s.isEmpty()) {
        return;
    }

    // List containing words formed in each iteration 
    List<String> strings = new LinkedList<String>();
    strings.add(String.valueOf(s.charAt(0))); // add the first element to the list

     // Temp list that holds the set of strings for 
     //  appending the current character to all position in each word in the original list
    List<String> tempList = new LinkedList<String>(); 

    for(int i=1; i< s.length(); i++) {

        for(int j=0; j<strings.size(); j++) {
            tempList.addAll(merge(s.charAt(i), strings.get(j)));
                        }
        strings.removeAll(strings);
        strings.addAll(tempList);

        tempList.removeAll(tempList);

    }

    for(int i=0; i<strings.size(); i++) {
        System.out.println(strings.get(i));
    }
}

/**
 * helper method that appends the given character at each position in the given string 
 * and returns a set of such modified strings 
 * - set removes duplicates if any(in case a character is repeated)
 */
private static Set<String> merge(Character c,  String s) {
    if(s==null || s.isEmpty()) {
        return null;
    }

    int len = s.length();
    StringBuilder sb = new StringBuilder();
    Set<String> list = new HashSet<String>();

    for(int i=0; i<= len; i++) {
        sb = new StringBuilder();
        sb.append(s.substring(0, i) + c + s.substring(i, len));
        list.add(sb.toString());
    }

    return list;
}
Jeya
sumber
solusi ini tampaknya salah System.out.println(permute("AABBC").size());menampilkan 45, tetapi sebenarnya 5! = 120
Mladen Adamovic
11

Mari kita gunakan input abcsebagai contoh.

Mulailah hanya dengan elemen terakhir ( c) dalam set ( ["c"]), lalu tambahkan elemen terakhir kedua ( b) ke depan, akhir dan setiap posisi yang mungkin ada di tengah, membuatnya ["bc", "cb"]dan kemudian dengan cara yang sama akan menambah elemen berikutnya dari belakang ( a) ke setiap string di set membuatnya:

"a" + "bc" = ["abc", "bac", "bca"]  and  "a" + "cb" = ["acb" ,"cab", "cba"] 

Demikian seluruh permutasi:

["abc", "bac", "bca","acb" ,"cab", "cba"]

Kode:

public class Test 
{
    static Set<String> permutations;
    static Set<String> result = new HashSet<String>();

    public static Set<String> permutation(String string) {
        permutations = new HashSet<String>();

        int n = string.length();
        for (int i = n - 1; i >= 0; i--) 
        {
            shuffle(string.charAt(i));
        }
        return permutations;
    }

    private static void shuffle(char c) {
        if (permutations.size() == 0) {
            permutations.add(String.valueOf(c));
        } else {
            Iterator<String> it = permutations.iterator();
            for (int i = 0; i < permutations.size(); i++) {

                String temp1;
                for (; it.hasNext();) {
                    temp1 = it.next();
                    for (int k = 0; k < temp1.length() + 1; k += 1) {
                        StringBuilder sb = new StringBuilder(temp1);

                        sb.insert(k, c);

                        result.add(sb.toString());
                    }
                }
            }
            permutations = result;
            //'result' has to be refreshed so that in next run it doesn't contain stale values.
            result = new HashSet<String>();
        }
    }

    public static void main(String[] args) {
        Set<String> result = permutation("abc");

        System.out.println("\nThere are total of " + result.size() + " permutations:");
        Iterator<String> it = result.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}
Vihaan Verma
sumber
1
Saya menyukai solusi Anda. Sangat intuitif dan dijelaskan dengan baik. Terima kasih banyak.
user2585781
9

Nah, inilah solusi yang elegan, non-rekursif, O (n!):

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;
    }
Adilli Adil
sumber
Solusi ini hanya berfungsi jika kata memiliki kurang dari 4 huruf, jika tidak hanya setengah dari array yang dihasilkan berisi kata-kata unik.
Maksim Maksimov
5

Salah satu solusi sederhana bisa saja tetap bertukar karakter secara rekursif menggunakan dua petunjuk.

public static void main(String[] args)
{
    String str="abcdefgh";
    perm(str);
}
public static void perm(String str)
{  char[] char_arr=str.toCharArray();
    helper(char_arr,0);
}
public static void helper(char[] char_arr, int i)
{
    if(i==char_arr.length-1)
    {
        // print the shuffled string 
            String str="";
            for(int j=0; j<char_arr.length; j++)
            {
                str=str+char_arr[j];
            }
            System.out.println(str);
    }
    else
    {
    for(int j=i; j<char_arr.length; j++)
    {
        char tmp = char_arr[i];
        char_arr[i] = char_arr[j];
        char_arr[j] = tmp;
        helper(char_arr,i+1);
        char tmp1 = char_arr[i];
        char_arr[i] = char_arr[j];
        char_arr[j] = tmp1;
    }
}
}
Katie
sumber
Ini mirip dengan solusi yang diberikan di sini: geeksforgeeks.org/… , yang melibatkan pengulangan dan kompleksitas waktu O (n * n!).
Nakul Kumar
5

implementasi python

def getPermutation(s, prefix=''):
        if len(s) == 0:
                print prefix
        for i in range(len(s)):
                getPermutation(s[0:i]+s[i+1:len(s)],prefix+s[i] )



getPermutation('abcd','')
riteshkasat
sumber
4

ini bekerja untuk saya ..

import java.util.Arrays;

public class StringPermutations{
    public static void main(String args[]) {
        String inputString = "ABC";
        permute(inputString.toCharArray(), 0, inputString.length()-1);
    }

    public static void permute(char[] ary, int startIndex, int endIndex) {
        if(startIndex == endIndex){
            System.out.println(String.valueOf(ary));
        }else{
            for(int i=startIndex;i<=endIndex;i++) {
                 swap(ary, startIndex, i );
                 permute(ary, startIndex+1, endIndex);
                 swap(ary, startIndex, i );
            }
        }
    }

    public static void swap(char[] ary, int x, int y) {
        char temp = ary[x];
        ary[x] = ary[y];
        ary[y] = temp;
    }
}
Arun Kumar Mudraboyina
sumber
3

Gunakan rekursi.

ketika input adalah string kosong, satu-satunya permutasi adalah string kosong. Coba untuk masing-masing huruf dalam string dengan menjadikannya sebagai huruf pertama dan kemudian temukan semua permutasi dari huruf yang tersisa menggunakan panggilan rekursif.

import java.util.ArrayList;
import java.util.List;

class Permutation {
    private static List<String> permutation(String prefix, String str) {
        List<String> permutations = new ArrayList<>();
        int n = str.length();
        if (n == 0) {
            permutations.add(prefix);
        } else {
            for (int i = 0; i < n; i++) {
                permutations.addAll(permutation(prefix + str.charAt(i), str.substring(i + 1, n) + str.substring(0, i)));
            }
        }
        return permutations;
    }

    public static void main(String[] args) {
        List<String> perms = permutation("", "abcd");

        String[] array = new String[perms.size()];
        for (int i = 0; i < perms.size(); i++) {
            array[i] = perms.get(i);
        }

        int x = array.length;

        for (final String anArray : array) {
            System.out.println(anArray);
        }
    }
}
coder101
sumber
3

Biarkan saya mencoba untuk mengatasi masalah ini dengan Kotlin:

fun <T> List<T>.permutations(): List<List<T>> {
    //escape case
    if (this.isEmpty()) return emptyList()

    if (this.size == 1) return listOf(this)

    if (this.size == 2) return listOf(listOf(this.first(), this.last()), listOf(this.last(), this.first()))

    //recursive case
    return this.flatMap { lastItem ->
        this.minus(lastItem).permutations().map { it.plus(lastItem) }
    }
}

Konsep inti: Memecah daftar panjang menjadi daftar + rekursi yang lebih kecil

Jawaban panjang dengan daftar contoh [1, 2, 3, 4]:

Bahkan untuk daftar 4 sudah agak membingungkan mencoba untuk mendaftar semua permutasi yang mungkin ada di kepala Anda, dan apa yang perlu kita lakukan adalah persis untuk menghindari itu. Sangat mudah bagi kita untuk memahami bagaimana membuat semua permutasi daftar ukuran 0, 1, dan 2, jadi yang perlu kita lakukan adalah memecahnya ke salah satu ukuran tersebut dan menggabungkannya kembali dengan benar. Bayangkan mesin jackpot: algoritma ini akan mulai berputar dari kanan ke kiri, dan menulis

  1. kembali kosong / daftar 1 ketika ukuran daftar adalah 0 atau 1
  2. menangani ketika ukuran daftar adalah 2 (misalnya [3, 4]), dan menghasilkan 2 permutasi ([3, 4] & [4, 3])
  3. Untuk setiap item, tandai sebagai yang terakhir di yang terakhir, dan temukan semua permutasi untuk sisa item dalam daftar. (mis. letakkan [4] di atas meja, dan lemparkan [1, 2, 3] ke permutasi lagi)
  4. Sekarang dengan semua permutasi itu adalah anak-anak, letakkan dirinya kembali ke akhir daftar (mis: [1, 2, 3] [, 4], [1, 3, 2] [, 4], [2, 3, 1] [, 4], ...)
Louis Tsai
sumber
2
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class hello {
    public static void main(String[] args) throws IOException {
        hello h = new hello();
        h.printcomp();
    }
      int fact=1;
    public void factrec(int a,int k){
        if(a>=k)
        {fact=fact*k;
        k++;
        factrec(a,k);
        }
        else
        {System.out.println("The string  will have "+fact+" permutations");
        }
        }
    public void printcomp(){
        String str;
        int k;
        Scanner in = new Scanner(System.in);
        System.out.println("enter the string whose permutations has to b found");
        str=in.next();
        k=str.length();
        factrec(k,1);
        String[] arr =new String[fact];
        char[] array = str.toCharArray();
        while(p<fact)
        printcomprec(k,array,arr);
            // if incase u need array containing all the permutation use this
            //for(int d=0;d<fact;d++)         
        //System.out.println(arr[d]);
    }
    int y=1;
    int p = 0;
    int g=1;
    int z = 0;
    public void printcomprec(int k,char array[],String arr[]){
        for (int l = 0; l < k; l++) {
            for (int b=0;b<k-1;b++){
            for (int i=1; i<k-g; i++) {
                char temp;
                String stri = "";
                temp = array[i];
                array[i] = array[i + g];
                array[i + g] = temp;
                for (int j = 0; j < k; j++)
                    stri += array[j];
                arr[z] = stri;
                System.out.println(arr[z] + "   " + p++);
                z++;
            }
            }
            char temp;
            temp=array[0];
            array[0]=array[y];
            array[y]=temp;
            if (y >= k-1)
                y=y-(k-1);
            else
                y++;
        }
        if (g >= k-1)
            g=1;
        else
            g++;
    }

}
Antony Johnson
sumber
2
/** Returns an array list containing all
 * permutations of the characters in s. */
public static ArrayList<String> permute(String s) {
    ArrayList<String> perms = new ArrayList<>();
    int slen = s.length();
    if (slen > 0) {
        // Add the first character from s to the perms array list.
        perms.add(Character.toString(s.charAt(0)));

        // Repeat for all additional characters in s.
        for (int i = 1;  i < slen;  ++i) {

            // Get the next character from s.
            char c = s.charAt(i);

            // For each of the strings currently in perms do the following:
            int size = perms.size();
            for (int j = 0;  j < size;  ++j) {

                // 1. remove the string
                String p = perms.remove(0);
                int plen = p.length();

                // 2. Add plen + 1 new strings to perms.  Each new string
                //    consists of the removed string with the character c
                //    inserted into it at a unique location.
                for (int k = 0;  k <= plen;  ++k) {
                    perms.add(p.substring(0, k) + c + p.substring(k));
                }
            }
        }
    }
    return perms;
}
Barzee
sumber
2

Berikut ini adalah solusi rekursif minimalis langsung di Jawa:

public static ArrayList<String> permutations(String s) {
    ArrayList<String> out = new ArrayList<String>();
    if (s.length() == 1) {
        out.add(s);
        return out;
    }
    char first = s.charAt(0);
    String rest = s.substring(1);
    for (String permutation : permutations(rest)) {
        out.addAll(insertAtAllPositions(first, permutation));
    }
    return out;
}
public static ArrayList<String> insertAtAllPositions(char ch, String s) {
    ArrayList<String> out = new ArrayList<String>();
    for (int i = 0; i <= s.length(); ++i) {
        String inserted = s.substring(0, i) + ch + s.substring(i);
        out.add(inserted);
    }
    return out;
}
Jay Taylor
sumber
2

Kita dapat menggunakan faktorial untuk menemukan berapa banyak string yang dimulai dengan huruf tertentu.

Contoh: ambil input abcd. (3!) == 6string akan dimulai dengan setiap huruf abcd.

static public int facts(int x){
    int sum = 1;
    for (int i = 1; i < x; i++) {
        sum *= (i+1);
    }
    return sum;
}

public static void permutation(String str) {
    char[] str2 = str.toCharArray();
    int n = str2.length;
    int permutation = 0;
    if (n == 1) {
        System.out.println(str2[0]);
    } else if (n == 2) {
        System.out.println(str2[0] + "" + str2[1]);
        System.out.println(str2[1] + "" + str2[0]);
    } else {
        for (int i = 0; i < n; i++) {
            if (true) {
                char[] str3 = str.toCharArray();
                char temp = str3[i];
                str3[i] = str3[0];
                str3[0] = temp;
                str2 = str3;
            }

            for (int j = 1, count = 0; count < facts(n-1); j++, count++) {
                if (j != n-1) {
                    char temp1 = str2[j+1];
                    str2[j+1] = str2[j];
                    str2[j] = temp1;
                } else {
                    char temp1 = str2[n-1];
                    str2[n-1] = str2[1];
                    str2[1] = temp1;
                    j = 1;
                } // end of else block
                permutation++;
                System.out.print("permutation " + permutation + " is   -> ");
                for (int k = 0; k < n; k++) {
                    System.out.print(str2[k]);
                } // end of loop k
                System.out.println();
            } // end of loop j
        } // end of loop i
    }
}
pengguna1685821
sumber
2

Inilah yang saya lakukan melalui pemahaman dasar tentang Permutasi dan pemanggilan fungsi Rekursif. Butuh sedikit waktu tetapi dilakukan secara mandiri.

public class LexicographicPermutations {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    String s="abc";
    List<String>combinations=new ArrayList<String>();
    combinations=permutations(s);
    Collections.sort(combinations);
    System.out.println(combinations);
}

private static List<String> permutations(String s) {
    // TODO Auto-generated method stub
    List<String>combinations=new ArrayList<String>();
    if(s.length()==1){
        combinations.add(s);
    }
    else{
        for(int i=0;i<s.length();i++){
            List<String>temp=permutations(s.substring(0, i)+s.substring(i+1));
            for (String string : temp) {
                combinations.add(s.charAt(i)+string);
            }
        }
    }
    return combinations;
}}

yang menghasilkan Output sebagai[abc, acb, bac, bca, cab, cba] .

Logika dasar di baliknya adalah

Untuk setiap karakter, anggap sebagai karakter pertama & temukan kombinasi karakter yang tersisa. mis [abc](Combination of abc)->.

  1. a->[bc](a x Combination of (bc))->{abc,acb}
  2. b->[ac](b x Combination of (ac))->{bac,bca}
  3. c->[ab](c x Combination of (ab))->{cab,cba}

Dan kemudian secara rekursif memanggil masing-masing [bc], [ac]& [ab]secara mandiri.

Shabbir Essaji
sumber
2

Implementasi Java tanpa rekursi

public Set<String> permutate(String s){
    Queue<String> permutations = new LinkedList<String>();
    Set<String> v = new HashSet<String>();
    permutations.add(s);

    while(permutations.size()!=0){
        String str = permutations.poll();
        if(!v.contains(str)){
            v.add(str);
            for(int i = 0;i<str.length();i++){
                String c = String.valueOf(str.charAt(i));
                permutations.add(str.substring(i+1) + c +  str.substring(0,i));
            }
        }
    }
    return v;
}
Hadi Elmougy
sumber
1

// masukkan setiap karakter ke dalam daftar array

static ArrayList al = new ArrayList();

private static void findPermutation (String str){
    for (int k = 0; k < str.length(); k++) {
        addOneChar(str.charAt(k));
    }
}

//insert one char into ArrayList
private static void addOneChar(char ch){
    String lastPerStr;
    String tempStr;
    ArrayList locAl = new ArrayList();
    for (int i = 0; i < al.size(); i ++ ){
        lastPerStr = al.get(i).toString();
        //System.out.println("lastPerStr: " + lastPerStr);
        for (int j = 0; j <= lastPerStr.length(); j++) {
            tempStr = lastPerStr.substring(0,j) + ch + 
                    lastPerStr.substring(j, lastPerStr.length());
            locAl.add(tempStr);
            //System.out.println("tempStr: " + tempStr);
        }
    }
    if(al.isEmpty()){
        al.add(ch);
    } else {
        al.clear();
        al = locAl;
    }
}

private static void printArrayList(ArrayList al){
    for (int i = 0; i < al.size(); i++) {
        System.out.print(al.get(i) + "  ");
    }
}
David Lee
sumber
Saya tidak menemukan jawaban ini berguna karena mengandung penjelasan dan menggunakan algoritma yang sama seperti beberapa jawaban lain yang melakukan memberikan penjelasan.
Bernhard Barker
1
//Rotate and create words beginning with all letter possible and push to stack 1

//Read from stack1 and for each word create words with other letters at the next location by rotation and so on 

/*  eg : man

    1. push1 - man, anm, nma
    2. pop1 - nma ,  push2 - nam,nma
       pop1 - anm ,  push2 - amn,anm
       pop1 - man ,  push2 - mna,man
*/

public class StringPermute {

    static String str;
    static String word;
    static int top1 = -1;
    static int top2 = -1;
    static String[] stringArray1;
    static String[] stringArray2;
    static int strlength = 0;

    public static void main(String[] args) throws IOException {
        System.out.println("Enter String : ");
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader bfr = new BufferedReader(isr);
        str = bfr.readLine();
        word = str;
        strlength = str.length();
        int n = 1;
        for (int i = 1; i <= strlength; i++) {
            n = n * i;
        }
        stringArray1 = new String[n];
        stringArray2 = new String[n];
        push(word, 1);
        doPermute();
        display();
    }

    public static void push(String word, int x) {
        if (x == 1)
            stringArray1[++top1] = word;
        else
            stringArray2[++top2] = word;
    }

    public static String pop(int x) {
        if (x == 1)
            return stringArray1[top1--];
        else
            return stringArray2[top2--];
    }

    public static void doPermute() {

        for (int j = strlength; j >= 2; j--)
            popper(j);

    }

    public static void popper(int length) {
        // pop from stack1 , rotate each word n times and push to stack 2
        if (top1 > -1) {
            while (top1 > -1) {
                word = pop(1);
                for (int j = 0; j < length; j++) {
                    rotate(length);
                    push(word, 2);
                }
            }
        }
        // pop from stack2 , rotate each word n times w.r.t position and push to
        // stack 1
        else {
            while (top2 > -1) {
                word = pop(2);
                for (int j = 0; j < length; j++) {
                    rotate(length);
                    push(word, 1);
                }
            }
        }

    }

    public static void rotate(int position) {
        char[] charstring = new char[100];
        for (int j = 0; j < word.length(); j++)
            charstring[j] = word.charAt(j);

        int startpos = strlength - position;
        char temp = charstring[startpos];
        for (int i = startpos; i < strlength - 1; i++) {
            charstring[i] = charstring[i + 1];
        }
        charstring[strlength - 1] = temp;
        word = new String(charstring).trim();
    }

    public static void display() {
        int top;
        if (top1 > -1) {
            while (top1 > -1)
                System.out.println(stringArray1[top1--]);
        } else {
            while (top2 > -1)
                System.out.println(stringArray2[top2--]);
        }
    }
}
nnc
sumber
1

Cara sederhana lainnya adalah dengan loop melalui string, pilih karakter yang belum digunakan dan letakkan di buffer, lanjutkan loop sampai ukuran buffer sama dengan panjang string. Saya lebih suka solusi pelacakan ini karena:

  1. Mudah dimengerti
  2. Mudah untuk menghindari duplikasi
  3. Outputnya diurutkan

Berikut adalah kode java:

List<String> permute(String str) {
  if (str == null) {
    return null;
  }

  char[] chars = str.toCharArray();
  boolean[] used = new boolean[chars.length];

  List<String> res = new ArrayList<String>();
  StringBuilder sb = new StringBuilder();

  Arrays.sort(chars);

  helper(chars, used, sb, res);

  return res;
}

void helper(char[] chars, boolean[] used, StringBuilder sb, List<String> res) {
  if (sb.length() == chars.length) {
    res.add(sb.toString());
    return;
  }

  for (int i = 0; i < chars.length; i++) {
    // avoid duplicates
    if (i > 0 && chars[i] == chars[i - 1] && !used[i - 1]) {
      continue;
    }

    // pick the character that has not used yet
    if (!used[i]) {
      used[i] = true;
      sb.append(chars[i]);

      helper(chars, used, sb, res);

      // back tracking
      sb.deleteCharAt(sb.length() - 1);
      used[i] = false;
    }
  }
}

Input str: 1231

Daftar keluaran: {1123, 1132, 1213, 1231, 1312, 1321, 2113, 2131, 2311, 3112, 3121, 3211}

Memperhatikan bahwa output diurutkan, dan tidak ada hasil duplikat.

jeantimex
sumber
1

Rekursi tidak diperlukan, bahkan Anda dapat menghitung permutasi secara langsung , solusi ini menggunakan obat generik untuk mengubah urutan array apa pun.

Berikut adalah informasi yang bagus tentang algoritme ini.

Untuk pengembang C # di sini adalah implementasi yang lebih bermanfaat.

public static void main(String[] args) {
    String word = "12345";

    Character[] array = ArrayUtils.toObject(word.toCharArray());
    long[] factorials = Permutation.getFactorials(array.length + 1);

    for (long i = 0; i < factorials[array.length]; i++) {
        Character[] permutation = Permutation.<Character>getPermutation(i, array, factorials);
        printPermutation(permutation);
    }
}

private static void printPermutation(Character[] permutation) {
    for (int i = 0; i < permutation.length; i++) {
        System.out.print(permutation[i]);
    }
    System.out.println();
}

Algoritma ini memiliki kompleksitas ruang dan waktu O (N) untuk menghitung setiap permutasi .

public class Permutation {
    public static <T> T[] getPermutation(long permutationNumber, T[] array, long[] factorials) {
        int[] sequence = generateSequence(permutationNumber, array.length - 1, factorials);
        T[] permutation = generatePermutation(array, sequence);

        return permutation;
    }

    public static <T> T[] generatePermutation(T[] array, int[] sequence) {
        T[] clone = array.clone();

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

        return clone;
    }

    private static int[] generateSequence(long permutationNumber, int size, long[] factorials) {
        int[] sequence = new int[size];

        for (int j = 0; j < sequence.length; j++) {
            long factorial = factorials[sequence.length - j];
            sequence[j] = (int) (permutationNumber / factorial);
            permutationNumber = (int) (permutationNumber % factorial);
        }

        return sequence;
    }

    private static <T> void swap(T[] array, int i, int j) {
        T t = array[i];
        array[i] = array[j];
        array[j] = t;
    }

    public static long[] getFactorials(int length) {
        long[] factorials = new long[length];
        long factor = 1;

        for (int i = 0; i < length; i++) {
            factor *= i <= 1 ? 1 : i;
            factorials[i] = factor;
        }

        return factorials;
    }
}
Najera
sumber
1

Permutasi String:

public static void main(String args[]) {
    permu(0,"ABCD");
}

static void permu(int fixed,String s) {
    char[] chr=s.toCharArray();
    if(fixed==s.length())
        System.out.println(s);
    for(int i=fixed;i<s.length();i++) {
        char c=chr[i];
        chr[i]=chr[fixed];
        chr[fixed]=c;
        permu(fixed+1,new String(chr));
    }   
}
sakivns
sumber
1

Berikut adalah metode lain yang lebih sederhana untuk melakukan Permutasi string.

public class Solution4 {
public static void main(String[] args) {
    String  a = "Protijayi";
  per(a, 0);

}

static void per(String a  , int start ) {
      //bse case;
    if(a.length() == start) {System.out.println(a);}
    char[] ca = a.toCharArray();
    //swap 
    for (int i = start; i < ca.length; i++) {
        char t = ca[i];
        ca[i] = ca[start];
        ca[start] = t;
        per(new String(ca),start+1);
    }

}//per

}
Soudipta Dutta
sumber
1

Implementasi java untuk mencetak semua permutasi dari string yang diberikan mempertimbangkan karakter duplikat dan hanya mencetak karakter unik adalah sebagai berikut:

import java.util.Set;
import java.util.HashSet;

public class PrintAllPermutations2
{
    public static void main(String[] args)
    {
        String str = "AAC";

    PrintAllPermutations2 permutation = new PrintAllPermutations2();

    Set<String> uniqueStrings = new HashSet<>();

    permutation.permute("", str, uniqueStrings);
}

void permute(String prefixString, String s, Set<String> set)
{
    int n = s.length();

    if(n == 0)
    {
        if(!set.contains(prefixString))
        {
            System.out.println(prefixString);
            set.add(prefixString);
        }
    }
    else
    {
        for(int i=0; i<n; i++)
        {
            permute(prefixString + s.charAt(i), s.substring(0,i) + s.substring(i+1,n), set);
        }
    }
}
}
Paul92
sumber
0
/*
     * eg: abc =>{a,bc},{b,ac},{c,ab}
     * =>{ca,b},{cb,a}
     * =>cba,cab
     * =>{ba,c},{bc,a}
     * =>bca,bac
     * =>{ab,c},{ac,b}
     * =>acb,abc
     */
    public void nonRecpermute(String prefix, String word)
    {
        String[] currentstr ={prefix,word};
        Stack<String[]> stack = new Stack<String[]>();
        stack.add(currentstr);
        while(!stack.isEmpty())
        {
            currentstr = stack.pop();
            String currentPrefix = currentstr[0];
            String currentWord = currentstr[1];
            if(currentWord.equals(""))
            {
                System.out.println("Word ="+currentPrefix);
            }
            for(int i=0;i<currentWord.length();i++)
            {
                String[] newstr = new String[2];
                newstr[0]=currentPrefix + String.valueOf(currentWord.charAt(i));
                newstr[1] = currentWord.substring(0, i);
                if(i<currentWord.length()-1)
                {
                    newstr[1] = newstr[1]+currentWord.substring(i+1);
                }
                stack.push(newstr);
            }

        }

    }
nnc
sumber
0

Ini dapat dilakukan secara iteratif dengan hanya memasukkan setiap huruf dari string pada gilirannya di semua lokasi dari hasil parsial sebelumnya.

Kita mulai dengan [A], yang dengan Bmenjadi [BA, AB], dan dengan C, [CBA, BCA, BAC, CAB, etc].

Waktu berjalan akan menjadi O(n!), yang, untuk kasus uji ABCD, adalah 1 x 2 x 3 x 4.

Dalam produk di atas, 1untuk A, 2untuk B, dll.

Sampel dart:

void main() {

  String insertAt(String a, String b, int index)
  {
    return a.substring(0, index) + b + a.substring(index);
  }

  List<String> Permute(String word) {

    var letters = word.split('');

    var p_list = [ letters.first ];

    for (var c in letters.sublist(1)) {

      var new_list = [ ];

      for (var p in p_list)
        for (int i = 0; i <= p.length; i++)
          new_list.add(insertAt(p, c, i));

      p_list = new_list;
    }

    return p_list;
  }

  print(Permute("ABCD"));

}
Troy Dawson
sumber
0

Berikut ini adalah implementasi java:

/* All Permutations of a String */

import java.util.*;
import java.lang.*;
import java.io.*;

/* Complexity O(n*n!) */
class Ideone
{
     public static ArrayList<String> strPerm(String str, ArrayList<String> list)
     {
        int len = str.length();
        if(len==1){
            list.add(str);
            return list;
        }

        list = strPerm(str.substring(0,len-1),list);
        int ls = list.size();
        char ap = str.charAt(len-1);
        for(int i=0;i<ls;i++){
            String temp = list.get(i);
            int tl = temp.length();
            for(int j=0;j<=tl;j++){
                list.add(temp.substring(0,j)+ap+temp.substring(j,tl));  
            }
        }

        while(true){
            String temp = list.get(0);
            if(temp.length()<len)
                list.remove(temp);
            else
                break;
        }

        return list;
    }

    public static void main (String[] args) throws java.lang.Exception
    {
        String str = "abc";
        ArrayList<String> list = new ArrayList<>();

        list = strPerm(str,list);
        System.out.println("Total Permutations : "+list.size());
        for(int i=0;i<list.size();i++)
            System.out.println(list.get(i));

    }
}

http://ideone.com/nWPb3k

Sahil Chhabra
sumber