简体   繁体   中英

permutations of a string using iteration

I'm trying to find permutation of a given string, but I want to use iteration. The recursive solution I found online and I do understand it, but converting it to an iterative solution is really not working out. Below I have attached my code. I would really appreciate the help:

public static void combString(String s) {
    char[] a = new char[s.length()];
    //String temp = "";
    for(int i = 0; i < s.length(); i++) {
        a[i] = s.charAt(i);
    }
    for(int i = 0; i < s.length(); i++) {
        String temp = "" + a[i];    

        for(int j = 0; j < s.length();j++) {
            //int k = j;
            if(i != j) {
                System.out.println(j);
                temp += s.substring(0,j) + s.substring(j+1,s.length());
            }               
        }
        System.out.println(temp);
    }
}

Following up on my related question comment, here's a Java implementation that does what you want using the Counting QuickPerm Algorithm :

public static void combString(String s) {
    // Print initial string, as only the alterations will be printed later
    System.out.println(s);   
    char[] a = s.toCharArray();
    int n = a.length;
    int[] p = new int[n];  // Weight index control array initially all zeros. Of course, same size of the char array.
    int i = 1; //Upper bound index. i.e: if string is "abc" then index i could be at "c"
    while (i < n) {
        if (p[i] < i) { //if the weight index is bigger or the same it means that we have already switched between these i,j (one iteration before).
            int j = ((i % 2) == 0) ? 0 : p[i];//Lower bound index. i.e: if string is "abc" then j index will always be 0.
            swap(a, i, j);
            // Print current
            System.out.println(join(a));
            p[i]++; //Adding 1 to the specific weight that relates to the char array.
            i = 1; //if i was 2 (for example), after the swap we now need to swap for i=1
        }
        else { 
            p[i] = 0;//Weight index will be zero because one iteration before, it was 1 (for example) to indicate that char array a[i] swapped.
            i++;//i index will have the option to go forward in the char array for "longer swaps"
        }
    }
}

private static String join(char[] a) {
    StringBuilder builder = new StringBuilder();
    builder.append(a);
    return builder.toString();
}

private static void swap(char[] a, int i, int j) {
    char temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}
    List<String> results = new ArrayList<String>();
    String test_str = "abcd";
    char[] chars = test_str.toCharArray();
    results.add(new String("" + chars[0]));
    for(int j=1; j<chars.length; j++) {
        char c = chars[j];
        int cur_size = results.size();
        //create new permutations combing char 'c' with each of the existing permutations
        for(int i=cur_size-1; i>=0; i--) {
            String str = results.remove(i);
            for(int l=0; l<=str.length(); l++) {
                results.add(str.substring(0,l) + c + str.substring(l));
            }
        }
    }
    System.out.println("Number of Permutations: " + results.size());
    System.out.println(results);

Example: if we have 3 character string eg "abc", we can form permuations as below.

1) construct a string with first character eg 'a' and store that in results.

    char[] chars = test_str.toCharArray();
    results.add(new String("" + chars[0]));

2) Now take next character in string (ie 'b') and insert that in all possible positions of previously contsructed strings in results. Since we have only one string in results ("a") at this point, doing so gives us 2 new strings 'ba', 'ab'. Insert these newly constructed strings in results and remove "a".

    for(int i=cur_size-1; i>=0; i--) {
        String str = results.remove(i);
        for(int l=0; l<=str.length(); l++) {
            results.add(str.substring(0,l) + c + str.substring(l));
        }
    }

3) Repeat 2) for every character in the given string.

for(int j=1; j<chars.length; j++) {
    char c = chars[j];
     ....
     ....
}

This gives us "cba", "bca", "bac" from "ba" and "cab", "acb" and "abc" from "ab"

Work queue allows us to create an elegant iterative solution for this problem.

static List<String> permutations(String string) {
    List<String> permutations = new LinkedList<>();
    Deque<WorkUnit> workQueue = new LinkedList<>(); 

    // We need to permutate the whole string and haven't done anything yet.
    workQueue.add(new WorkUnit(string, ""));

    while (!workQueue.isEmpty()) { // Do we still have any work?
        WorkUnit work = workQueue.poll();

        // Permutate each character.
        for (int i = 0; i < work.todo.length(); i++) {
            String permutation = work.done + work.todo.charAt(i);

            // Did we already build a complete permutation?
            if (permutation.length() == string.length()) {
                permutations.add(permutation);
            } else {

                // Otherwise what characters are left? 
                String stillTodo = work.todo.substring(0, i) + work.todo.substring(i + 1);
                workQueue.add(new WorkUnit(stillTodo, permutation));
            }
        }
    }
    return permutations; 
}

A helper class to hold partial results is very simple.

/**
 * Immutable unit of work
 */
class WorkUnit {
    final String todo;
    final String done;

    WorkUnit(String todo, String done) {
        this.todo = todo;
        this.done = done;
    }
}

You can test the above piece of code by wrapping them in this class.

import java.util.*;

public class AllPermutations {

    public static void main(String... args) {
        String str = args[0];
        System.out.println(permutations(str));
    }

    static List<String> permutations(String string) {
        ...
    }
}

class WorkUnit {
    ...
}

Try it by compiling and running.

$ javac AllPermutations.java; java AllPermutations abcd

The below implementation can also be easily tweaked to return a list of permutations in reverse order by using a LIFO stack of work instead of a FIFO queue.

import java.util.List;
import java.util.Set;
import java.util.ArrayList;
import java.util.HashSet;

public class Anagrams{

    public static void main(String[] args)
    {

        String inpString = "abcd";
        Set<String> combs = getAllCombs(inpString);

        for(String comb : combs)
        {
            System.out.println(comb);
        }

    }


    private static Set<String> getAllCombs(String inpString)
    {
        Set<String> combs = new HashSet<String>();
        if( inpString == null | inpString.isEmpty())
            return combs;

        combs.add(inpString.substring(0,1));
        Set<String> tempCombs = new HashSet<String>();
        for(char a : inpString.substring(1).toCharArray())
        {
            tempCombs.clear();
            tempCombs.addAll(combs);
            combs.clear();
            for(String comb : tempCombs)
            {
                combs.addAll(getCombs(comb,a));
            }
        }
        return combs;
    }

    private static Set<String> getCombs(String comb, char a) {
        Set<String> combs = new HashSet<String>();
        for(int i = 0 ; i <= comb.length(); i++)
        {
            String temp = comb.substring(0, i) + a + comb.substring(i);
            combs.add(temp);
            //System.out.println(temp);
        }
        return combs;
    }   
}

Just posting my approach to the problem:

import java.util.ArrayDeque;
import java.util.Queue;

public class PermutationIterative {
    public static void main(String[] args) {
        permutationIterative("abcd");
    }

    private static void permutationIterative(String str) {
        Queue<String> currentQueue = null;
        int charNumber = 1;
        for (char c : str.toCharArray()) {
            if (currentQueue == null) {
                currentQueue = new ArrayDeque<>(1);
                currentQueue.add(String.valueOf(c));
            } else {
                int currentQueueSize = currentQueue.size();
                int numElements = currentQueueSize * charNumber;
                Queue<String> nextQueue = new ArrayDeque<>(numElements);
                for (int i = 0; i < currentQueueSize; i++) {
                    String tempString = currentQueue.remove();
                    for (int j = 0; j < charNumber; j++) {
                        int n = tempString.length();
                        nextQueue.add(tempString.substring(0, j) + c + tempString.substring(j, n));
                    }
                }
                currentQueue = nextQueue;
            }
            charNumber++;
        }
        System.out.println(currentQueue);
    }
}
package vishal villa;

import java.util.Scanner;

public class Permutation {
    static void result( String st, String ans)
    {

        if(st.length() == 0)
            System.out.println(ans +" ");

        for(int i = 0; i<st.length(); i++)
        {
            char ch = st.charAt(i);
            String r = st.substring(0, i) +  st.substring(i + 1);
            result(r, ans + ch);    
        }   
    }
    public static void main(String[] args) 
    {
        Scanner Sc = new Scanner(System.in);
        System.out.println("enter the string");
        String st = Sc.nextLine();
    Permutation p = new Permutation();
        p.result(st,"" );
    }
}
// Java program to print all permutations of a
// given string.
public class Permutation
{
    public static void main(String[] args)
    {
        String str = "ABC";
        int n = str.length();
        Permutation permutation = new Permutation();
        permutation.permute(str, 0, n-1);
    }

    /**
     * permutation function
     * @param str string to calculate permutation for
     * @param s starting index
     * @param e end index
     */
    private void permute(String str, int s, int e)
    {
        if (s == e)
            System.out.println(str);
        else
        {
            for (int i = s; i <= s; i++)
            {
                str = swap(str,l,i);
                permute(str, s+1, e);
                str = swap(str,l,i);
            }
        }
    }

    /**
     * Swap Characters at position
     * @param a string value
     * @param i position 1
     * @param j position 2
     * @return swapped string
     */
    public String swap(String a, int i, int j)
    {
        char temp;
        char[] charArray = a.toCharArray();
        temp = charArray[i] ;
        charArray[i] = charArray[j];
        charArray[j] = temp;
        return String.valueOf(charArray);
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM