Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Permutation of array

For example I have this array:

int a[] = new int[]{3,4,6,2,1}; 

I need list of all permutations such that if one is like this, {3,2,1,4,6}, others must not be the same. I know that if the length of the array is n then there are n! possible combinations. How can this algorithm be written?

Update: thanks, but I need a pseudo code algorithm like:

for(int i=0;i<a.length;i++){     // code here } 

Just algorithm. Yes, API functions are good, but it does not help me too much.

like image 228
dato datuashvili Avatar asked May 27 '10 10:05

dato datuashvili


People also ask

How do you find the permutation of an array?

You take first element of an array (k=0) and exchange it with any element (i) of the array. Then you recursively apply permutation on array starting with second element. This way you get all permutations starting with i-th element.

How many permutations does an array have?

Therefore, if N is the size of the array and M is the number of elements in the array with its occurrence = 2, then the number of permutations satisfying the condition will be 2(N–(2*X)–1).

What is next permutation of an array?

Given an array A[] of N distinct integers. The task is to return the lexicographically greater permutation than the given arrangement. If no such arrangement is possible, return the array sorted in non-decreasing order.

How do you Permute two arrays?

Assume asort[] be sorted a[] in ascending order and bsort[] be sorted b[] in descending order. Let new permutation b[] is created by swapping any two indices i, j of bsort[], Case 1: i < j and element at b[i] is now bsort[j].


1 Answers

Here is how you can print all permutations in 10 lines of code:

public class Permute{     static void permute(java.util.List<Integer> arr, int k){         for(int i = k; i < arr.size(); i++){             java.util.Collections.swap(arr, i, k);             permute(arr, k+1);             java.util.Collections.swap(arr, k, i);         }         if (k == arr.size() -1){             System.out.println(java.util.Arrays.toString(arr.toArray()));         }     }     public static void main(String[] args){         Permute.permute(java.util.Arrays.asList(3,4,6,2,1), 0);     } } 

You take first element of an array (k=0) and exchange it with any element (i) of the array. Then you recursively apply permutation on array starting with second element. This way you get all permutations starting with i-th element. The tricky part is that after recursive call you must swap i-th element with first element back, otherwise you could get repeated values at the first spot. By swapping it back we restore order of elements (basically you do backtracking).

Iterators and Extension to the case of repeated values

The drawback of previous algorithm is that it is recursive, and does not play nicely with iterators. Another issue is that if you allow repeated elements in your input, then it won't work as is.

For example, given input [3,3,4,4] all possible permutations (without repetitions) are

[3, 3, 4, 4] [3, 4, 3, 4] [3, 4, 4, 3] [4, 3, 3, 4] [4, 3, 4, 3] [4, 4, 3, 3] 

(if you simply apply permute function from above you will get [3,3,4,4] four times, and this is not what you naturally want to see in this case; and the number of such permutations is 4!/(2!*2!)=6)

It is possible to modify the above algorithm to handle this case, but it won't look nice. Luckily, there is a better algorithm (I found it here) which handles repeated values and is not recursive.

First note, that permutation of array of any objects can be reduced to permutations of integers by enumerating them in any order.

To get permutations of an integer array, you start with an array sorted in ascending order. You 'goal' is to make it descending. To generate next permutation you are trying to find the first index from the bottom where sequence fails to be descending, and improves value in that index while switching order of the rest of the tail from descending to ascending in this case.

Here is the core of the algorithm:

//ind is an array of integers for(int tail = ind.length - 1;tail > 0;tail--){     if (ind[tail - 1] < ind[tail]){//still increasing          //find last element which does not exceed ind[tail-1]         int s = ind.length - 1;         while(ind[tail-1] >= ind[s])             s--;          swap(ind, tail-1, s);          //reverse order of elements in the tail         for(int i = tail, j = ind.length - 1; i < j; i++, j--){             swap(ind, i, j);         }         break;     } } 

Here is the full code of iterator. Constructor accepts an array of objects, and maps them into an array of integers using HashMap.

import java.lang.reflect.Array; import java.util.*; class Permutations<E> implements  Iterator<E[]>{      private E[] arr;     private int[] ind;     private boolean has_next;      public E[] output;//next() returns this array, make it public      Permutations(E[] arr){         this.arr = arr.clone();         ind = new int[arr.length];         //convert an array of any elements into array of integers - first occurrence is used to enumerate         Map<E, Integer> hm = new HashMap<E, Integer>();         for(int i = 0; i < arr.length; i++){             Integer n = hm.get(arr[i]);             if (n == null){                 hm.put(arr[i], i);                 n = i;             }             ind[i] = n.intValue();         }         Arrays.sort(ind);//start with ascending sequence of integers           //output = new E[arr.length]; <-- cannot do in Java with generics, so use reflection         output = (E[]) Array.newInstance(arr.getClass().getComponentType(), arr.length);         has_next = true;     }      public boolean hasNext() {         return has_next;     }      /**      * Computes next permutations. Same array instance is returned every time!      * @return      */     public E[] next() {         if (!has_next)             throw new NoSuchElementException();          for(int i = 0; i < ind.length; i++){             output[i] = arr[ind[i]];         }           //get next permutation         has_next = false;         for(int tail = ind.length - 1;tail > 0;tail--){             if (ind[tail - 1] < ind[tail]){//still increasing                  //find last element which does not exceed ind[tail-1]                 int s = ind.length - 1;                 while(ind[tail-1] >= ind[s])                     s--;                  swap(ind, tail-1, s);                  //reverse order of elements in the tail                 for(int i = tail, j = ind.length - 1; i < j; i++, j--){                     swap(ind, i, j);                 }                 has_next = true;                 break;             }          }         return output;     }      private void swap(int[] arr, int i, int j){         int t = arr[i];         arr[i] = arr[j];         arr[j] = t;     }      public void remove() {      } } 

Usage/test:

    TCMath.Permutations<Integer> perm = new TCMath.Permutations<Integer>(new Integer[]{3,3,4,4,4,5,5});     int count = 0;     while(perm.hasNext()){         System.out.println(Arrays.toString(perm.next()));         count++;     }     System.out.println("total: " + count); 

Prints out all 7!/(2!*3!*2!)=210 permutations.

like image 123
Yevgen Yampolskiy Avatar answered Sep 20 '22 23:09

Yevgen Yampolskiy