This question already has answers here:
Getting permutations of an int[] removing duplicates sets
(5 answers)
Closed 7 years ago.
I want to generate all distinct permutations of array of integers. The array may contain duplicates. but i want to generate all distinct permutations. I have tried next permutation and recursive methods which tend to be very slow. Please suggest.
There are n! different permutations of n elements. Generating a single permutation is cost n (strictly) so the minimum cost of any permutation generation algorithm would be O(n*n!)
Steinhaus–Johnson–Trotter algorithm is one of those algorithms. There are improvements like Shimon Even's and other algorithms like Heap's but none get them under O(n*n!)
Googling "permutation algorithm" gets several different algorithms you can implement, although most use recursion and that means another stack step. Steinhaus–Johnson–Trotter is defined as iterative, so shouldn't get that problem.
Here's a Java implementation
import java.util.Arrays;
import java.util.Iterator;
/**
* this implementation is based in Steinhaus–Johnson–Trotter algorithm and
* Shimon Even's improvement;
*
* #see https
* ://en.wikipedia.org/wiki/Steinhaus%E2%80%93Johnson%E2%80%93Trotter_algorithm
*
*/
public class Permutations implements Iterator<int[]> {
/**
* direction[i] = -1 if the element i has to move to the left, +1 to the
* right, 0 if it does not need to move
*/
private int[] direction;
/**
* inversePermutation[i] is the position of element i in permutation; It's
* called inverse permutation because if p2 is the inverse permutation of
* p1, then p1 is the inverse permutation of p2
*/
private int[] inversePermutation;
/**
* current permutation
*/
private int[] permutation;
/**
* #param numElements
* >= 1
*/
public Permutations(int numElements) {
// initial permutation
permutation = new int[numElements];
for (int i = 0; i < numElements; i++) {
permutation[i] = i;
}
// the support elements
inversePermutation = Arrays.copyOf(permutation, numElements);
direction = new int[numElements];
Arrays.fill(direction, -1);
direction[0] = 0;
}
/**
* Swaps the elements in array at positions i1 and i2
*
* #param array
* #param i1
* #param i2
*/
private static void swap(int[] array, int i1, int i2) {
int temp = array[i1];
array[i1] = array[i2];
array[i2] = temp;
}
/**
* prepares permutation to be the next one to return
*/
private void buildNextPermutation() {
// find the largest element with a nonzero direction, and swaps it in
// the indicated direction
int index = -1;
for (int i = 0; i < direction.length; i++) {
if (direction[permutation[i]] != 0
&& (index < 0 || permutation[index] < permutation[i])) {
index = i;
}
}
if (index < 0) {
// there are no more permutations
permutation = null;
} else {
// element we're moving
int chosenElement = permutation[index];
// direction we're moving
int dir = direction[chosenElement];
// index2 is the new position of chosenElement
int index2 = index + dir;
// we'll swap positions elements permutation[index] and
// permutation[index2] in permutation, to keep inversePermutation we
// have to swap inversePermutation's elements at index
// permutation[index] and permutation[index2]
swap(inversePermutation, permutation[index], permutation[index2]);
swap(permutation, index, index2);
// update directions
if (index2 == 0 || index2 == permutation.length - 1
|| permutation[index2 + dir] > permutation[index2]) {
// direction of chosen element
direction[chosenElement] = 0;
}
// all elements greater that chosenElement set its direction to +1
// if they're before index-1 or -1 if they're after
for (int i = chosenElement + 1; i < direction.length; i++) {
if (inversePermutation[i] > index2) {
direction[i] = -1;
} else {
direction[i] = 1;
}
}
}
}
#Override
public boolean hasNext() {
return permutation != null;
}
#Override
public int[] next() {
int[] result = Arrays.copyOf(permutation, permutation.length);
buildNextPermutation();
return result;
}
}
Related
For a Java class we have to make a Dynamic array. Cannot use arraylist.
Here is where I define the class
public class DynamicArray {
private int array[];
private int size;
Here is the called constructor:
/**
* DynamicArray copies the array
* #param obj
*/
public DynamicArray(DynamicArray obj) {
array = obj.toArray();
size = obj.getSize();
}
Under the main method, here is where I create the new array object and try to sort and shuffle (as well as a few of the other methods, but those are working):
/**
* Calling the copy constructor, which calls the toArray method
* Calling get method
* Calling indexOfMethod
* Calling findMax
* Calling findMin
* Calling shuffle
*/
DynamicArray array3 = new DynamicArray(array2);
array3.push(100);
array3.push(150);
array3.push(100);
System.out.println(array3);
array3.pop();
System.out.println(array3);
System.out.println("This number is at index 5: " + array3.get(5));
System.out.println("The number 100 first appears at index: " + array3.indexOf(100));
System.out.println("The highest number is: " + array3.findMax());
System.out.println("The lowest number is: " + array3.findMin());
System.out.println(array3);
array3.shuffle();
System.out.println(array3);
array3.sort(array3.toArray());
The toArray method is this:
/**
* toArray accessor returns the array
* #return
*/
public int[] toArray() {
int arrayCopy[] = new int[array.length];
for (int i = 0; i < array.length; i++) {
arrayCopy[i] = array[i];
}
return arrayCopy;
}
And the sort and shuffle methods are this:
/**
* isEmpty returns size = 0 is array is empty
* #return 0 if empty
*/
public boolean isEmpty() {
return size == 0;
}
/**
* sort sorts the numbers in the array
*/
public void sort(int [] array) {
int lastPos;
int index;
int newNum;
for (lastPos = array.length - 1; lastPos >= 0; lastPos--) {
for (index = 0; index <= lastPos - 1; index++) {
if (array[index] > array[index + 1]) {
newNum = array[index];
array[index] = array[index + 1];
array[index + 1] = newNum;
}
}
}
}
/**
* shuffle shuffles the array
*/
public void shuffle() {
Random r = new Random();
for (int i = array.length - 1; i > 0; i--) {
int index = r.nextInt(i);
int tmp = array[i];
array[i] = array[index];
array[index] = tmp;
}
}
The output for sort has 0's in it:
0, 0, 0, 10, 0, 0, 150, 0, 2,
And shuffle is not changing anything.
These were created with help in the tutoring lab and I've compared them to recommendations online.
What's going on?
Updated:
Here's the array2:
/**
* Calling constructor with parameter
* also calling push to add items to the array
*/
DynamicArray array2 = new DynamicArray(5);
array2.push(4);
array2.push(10);
array2.push(15);
array2.push(18);
array2.push(2);
array2.push(25);
System.out.println("Size is: " + array2.getSize());
array2.push(20);
System.out.println("Size is: " + array2.getSize());
System.out.println(array2);
Here's getSize()
/**
* getSize gets size of the array
* #return size
*/
public int getSize() {
return size;
}
Could you please provide information how array2 is instantinated? It is starting point for the algorithm.
getSize() implementation would be useful also.
For now you can check sorting algorithms here:
https://www.geeksforgeeks.org/sorting-algorithms/
e.g. Bubble sort is quite easy to understand and implement.
For shuffling implementation you can check:
http://www.vogella.com/tutorials/JavaAlgorithmsShuffle/article.html
So I have a Shifter program that only allows positive integers.
Question: how do I make it so It also receives negative numbers. I.e
Program ask for number of shifts, I enter 3 and it outputs
3 2 1 15 14 13 12 11 10 9 8 7 6 5 4
public static void shiftRight(int[] list)
{
if (list.length < 2) return;
int last = list[list.length - 1];
for(int i = list.length - 1; i > 0; i--) {
list[i] = list[i - 1];
}
list[0] = last;
}
if this is to shift right. How would I make it so It will shift depending on the number I input? i.e. Right for positive and Left for negative.
I would implement a shiftLeft(int[]) method according your method, and then decide which use
int input;
int[] array;
//fill the input, array etc.
if(input<0){
for(int i=0;i<-input;i++){
shiftLeft(array);
}
}else{
for(int i=0;i<input;i++){
shiftRight(array);
}
}
btw, this shifting is not very efficient way.
You could use the following function. It uses a temporary array to store the rotated/shifted array and then copies back to the original array. The arrays that is original array and temporary array are traversed twice, so it will be efficient instead for calling a shift function on the array many times.
/**
* This function performs the right/left shift operations
* on the array of integers.
*
* #param int[] array array of integers
* #param int shift Amount of right or
* left shift. If shift
* is grater than zero,
* function performs
* right shift, otherwise
* the function perform
* left shift.
*/
public static void shift_array (int[] array, int shift) {
/*
* If array is null, then return
* from the function.
*/
if (array == null) {
return;
}
boolean is_left_shift = (shift < 0); // store whether
// left shift is
// intended.
int shift_amount; // store the amount of shift
int array_length = array.length; // length of the
// array
if (shift < 0) {
shift_amount = shift * -1; // if shift is less than zero
// then shift_amount is set as
// product of shift and -1.
} else {
shift_amount = shift;
}
/*
* Make sure the shift_amount is within the
* length of the array.
*/
shift_amount = shift_amount % array_length;
/*
* If the shift_amount is zero, we
* have nothing to do. Return.
*/
if (shift_amount == 0) {
return;
}
/*
* Create a temp array and copy the
* elements in the array at appropriate
* positions.
*/
if (!is_left_shift) {
/*
* Temp array to store elements at shifted
* positions.
*/
int[] temp = new int[array_length];
/*
* Iterate throught the array
*/
for (int i = 0; i < array_length; ++i) {
int temp_index;
/*
* Map the elements to appropriate
* positions in the temp array.
*/
if ((i + shift_amount) < array_length) {
temp_index = i + shift_amount;
} else {
temp_index = (i + shift_amount) % array_length;;
}
/*
* Copy the array element into the temp array.
*/
temp[temp_index] = array[i];
}
/*
* Copy back from temp array to array
*/
for (int i = 0; i < array_length; ++i) {
array[i] = temp[i];
}
} else {
/*
* Temp array to store elements at shifted
* positions.
*/
int[] temp = new int[array_length];
/*
* Iterate throught the array
*/
for (int i = 0; i < array_length; ++i) {
int temp_index;
/*
* Map the elements to appropriate
* positions in the temp array.
*/
if ((i - shift_amount) >= 0) {
temp_index = i - shift_amount;
} else {
temp_index = i - shift_amount + array_length;
}
/*
* Copy the array element into the temp array.
*/
temp[temp_index] = array[i];
}
/*
* Copy back from temp array to array
*/
for (int i = 0; i < array_length; ++i) {
array[i] = temp[i];
}
}
}
Ok, so I have an implementation of a bubble sort, selection sort and insertion sort. I'm using Java.Random object to create three identical arrays of one hundred thousand numbers. I am passing these to each sort method in turn. I am timing the results using System.nanotime.
For some background information. The sort algorithms I followed for Selection and Insertion sort come from Frank Carano's "Data Structures and Abstraction's in Java 3rd Ed" The bubble sort, was off the top of my head.
Below I provide a self contained class that performs all this. Where have Carano's algorithms gone wrong I do not see it?
Below you will see I am counting the cycles of the base operations and timing the completion. At run time the number of cycles is negligibly different. For me when looking at completion time, Bubble is 1st, Selection is 2nd and Insertion is 3rd. This flies in the face of conventional wisdom. Why. Have I done something rather daft?
BTW you should be able to compile and run the provided code without any changes.
import java.util.Random;
/**
*
* Performs sorts on generic data, here using Integers.
*/
public class GenSorts {
static int selectionCount = 0, bubbleCount = 0, insertionCount = 0;;
//=========================================================================
/**
* Do an insertion sort.
* #param data The array to sort
* #param first The index of the first element
* #param lasr The index of the last element
*/
//=========================================================================
public static <T extends Comparable<? super T>> void insertionSort(T[]array, int first, int last){
for(int untouch = first + 1; untouch < last; untouch++){
T nextToInsert = array[untouch];
insertInOrder(nextToInsert, array, first, untouch-1);
}//end for
}//=========================================================================
//=========================================================================
/**
* Performs the shuffle and insert part of the insertion sort.
* #param anEntry The value to insert
* #param array The target array
* #param begin The begin of the unsorted part.
* #param end The end of the unsorted part.
*/
//=========================================================================
public static <T extends Comparable<? super T>> void insertInOrder(T anEntry, T[]array, int begin, int end){
int index = end;
//Do a shunt while an entry is less than the value at the index
while( ( index >= begin ) && (anEntry.compareTo(array[index]) < 0) ){
array[index+1] = array[index];
index --;
insertionCount++;
}
array[index+1] = anEntry;//Insert
}//======================================================================
//======================================================================
/**
* BUBBLE SORT///////////////////////////////////////////////////////////
* Perform a bubble sort on the data.
* #param data The array to be sorted.
*/
//======================================================================
public static <T extends Comparable <? super T> >void bubbleSort (T[] data)
{
Boolean swapped = true;
int stop = data.length -1;
while (swapped) {
swapped = false;
for (int x = 0; x < stop ; x++ ) {
bubbleCount++;
//if x smaller than x +1 swap
if ( data[x].compareTo( data[x+1] ) > 0 ) {
swap(x, x+1, data );
swapped = true;
}//end if
stop --;
}//end for
}//end while
}//end method============================================================
//========================================================================
/**
* SELECTION SORT/////////////////////////////////////////////////////////
* A selection sort algorithm to sort data.
* #param data
* #return
*/
//========================================================================
public static <T extends Comparable<? super T> > void selectionSort(T[] data, int n){
for (int index = 0; index < n - 1; index++)
{
selectionCount++;
int min = getSmallestIndex( index, n,data);
swap( index, min, data);
//DISPLAYME
// displaySelectionArray(index, min, data);
}
}//========================================================================
//==========================================================================
/**
* Get the index of the smallest item in the array from start to end/
* #param start The place in the array to start looking.
* #param end The place in the array to end looking.
* #param array The array to inspect.
* #returnThe index of the smallest.
*/
//==========================================================================
private static <T extends Comparable<? super T>> int getSmallestIndex( int start, int end, T[] array)
{
T min = array[start];//value of smallest
int minIndex = start;//index of smallest
for (int i = start + 1; i < end; i++)
{
// System.out.print(array[i].toString() + ", ");
if (array[i].compareTo(min) < 0)
{
minIndex = i;
min = array[i];
}//end if
}//end for
// System.out.println("");
return minIndex;
}//========================================================================
//=========================================================================
/**
* Swap emelement numbers j and iMin in array data.
* #param j
* #param iMin
* #param data
*/
//=========================================================================
public static<T extends Comparable <? super T> > void swap(int j, int iMin, T[] data){
T temp = data[j];
data[j] = data[iMin];
data[iMin] = temp;
}//end swap================================================================
public static Integer[] largeRandom1, largeRandom2, largeRandom3;
//========================================================================
/**
* Generate large integers for sorting.
* #param n The value of n.
*/
//========================================================================
public static void genLargeRandom(int n){
Random r = new Random();
largeRandom1 = new Integer[n];
largeRandom2 = new Integer[n];
largeRandom3 = new Integer[n];
for(int i = 0; i < n; i++){
largeRandom1[i] = r.nextInt(100);
largeRandom2[i] = largeRandom1[i];
largeRandom3[i] = largeRandom1[i];
}//end for
}//end genLarge//==========================================================
//=========================================================================
/**
* Sort a large numvber.
* #param args
*/
//=========================================================================
public static void main(String[] args){
genLargeRandom(100000);//one hundred thousand
Integer[] data = largeRandom1;///{40, 3, 2, 7, 4};
Integer[] data2 = largeRandom2;
Integer[] data3 = largeRandom3;
System.out.println("BUBBLE SORT!!");
Long t1s = System.nanoTime();
bubbleSort(data);///////////////Bubble Sort
Long t1e = System.nanoTime();
System.out.println("SELECTION SORT!!");
Long t2s = System.nanoTime();
selectionSort(data2, data2.length);///////////////Selection Sort
Long t2e = System.nanoTime();
System.out.println("INSERTION SORT!!");
Long t3s = System.nanoTime();
insertionSort(data3,0, data3.length);////////////Insertion Sort
Long t3e = System.nanoTime();
System.out.println("Bubble Time: " + (t1e - t1s));
System.out.println("Selection Time: " + (t2e - t2s));
System.out.println("insertion Time: " + (t3e - t3s));
System.out.println("Bubble count: " + bubbleCount );
System.out.println("Selection ccount :" + selectionCount );
System.out.println("Insertion ccount :" + selectionCount );
}//========================================================================
}//############################################################################
You've screwed up your bubble sort. Try to print the results for a simple input, and you'll see this clearly; for example, trying to sort (3, 2, 1) gives (2, 3, 1). You've misplaced the stop--:
public static <T extends Comparable <? super T> >void bubbleSort (T[] data)
{
Boolean swapped = true;
int stop = data.length -1;
while (swapped) {
swapped = false;
for (int x = 0; x < stop ; x++ ) {
bubbleCount++;
//if x smaller than x +1 swap
if ( data[x].compareTo( data[x+1] ) > 0 ) {
swap(x, x+1, data );
swapped = true;
}//end if
stop --; // needs to go outside the for
}//end for
}//end while
}//end method============================================================
The following algorithm is used to find a basin in matrix. The whole question is as follows:
2-D matrix is given where each cell represents height of cell. Water
can flow from cell with higher height to lower one. A basin is when
there is no cell with lower height in the neighbours
(left,right,up,down,diagonal). You have to find maximum size basin
block.
I have implemented the code. I am looking for timeComplexity. In my opinion time complexity is O(n * m) where n and m is the row and column of the matrix. Please verify.
public final class Basin {
private Basin() {}
private static enum Direction {
NW(-1, -1), N(0, -1), NE(-1, 1), E(0, 1), SE(1, 1), S(1, 0), SW(1, -1), W(-1, 0);
private int rowDelta;
private int colDelta;
Direction(int rowDelta, int colDelta) {
this.rowDelta = rowDelta;
this.colDelta = colDelta;
}
public int getRowDelta() {
return rowDelta;
}
public int getColDelta() {
return colDelta;
}
}
private static class BasinCount {
private int count;
private boolean isBasin;
private int item;
BasinCount(int count, boolean basin, int item) {
this.count = count;
this.isBasin = basin;
this.item = item;
}
};
/**
* Returns the minimum basin.
* If more than a single minimum basin exists then returns any arbitrary basin.
*
* #param m : the input matrix
* #return : returns the basin item and its size.
*/
public static BasinData getMaxBasin(int[][] m) {
if (m.length == 0) { throw new IllegalArgumentException("The matrix should contain atleast one element."); }
final boolean[][] visited = new boolean[m.length][m[0].length];
final List<BasinCount> basinCountList = new ArrayList<>();
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[0].length; j++) {
if (!visited[i][j]) {
basinCountList.add(scan(m, visited, i, j, m[i][j], new BasinCount(0, true, m[i][j])));
}
}
}
return getMaxBasin(basinCountList);
}
private static BasinData getMaxBasin(List<BasinCount> basinCountList) {
int maxCount = Integer.MIN_VALUE;
int item = 0;
for (BasinCount c : basinCountList) {
if (c.isBasin) {
if (c.count > maxCount) {
maxCount = c.count;
item = c.item;
}
}
}
return new BasinData(item, maxCount);
}
private static BasinCount scan(int[][] m, boolean[][] visited, int row, int col, int item, BasinCount baseCount) {
// array out of index
if (row < 0 || row == m.length || col < 0 || col == m[0].length) return baseCount;
// neighbor "m[row][col]" is lesser than me. now i cannot be the basin.
if (m[row][col] < item) {
baseCount.isBasin = false;
return baseCount;
}
// my neighbor "m[row][col]" is greater than me, thus not to add it to the basin.
if (m[row][col] > item) return baseCount;
// my neighbor is equal to me, but i happen to have visited him already. thus simply return without adding count.
// this is optimisitic recursion as described by rolf.
if (visited[row][col]) {
return baseCount;
}
visited[row][col] = true;
baseCount.count++;
for (Direction dir : Direction.values()) {
scan(m, visited, row + dir.getRowDelta(), col + dir.getColDelta(), item, baseCount);
/**
* once we know that current 'item' is not the basin, we do "want" to explore other dimensions.
* With the commented out code - consider: m3
* If the first 1 to be picked up is "1 # row2, col4." This hits zero, marks basin false and returns.
* Next time it starts with "1 # row 0, col 0". This never encounters zero, because "1 # row2, col4." is visited.
* this gives a false answer.
*/
// if (!baseCount.basin) {
// System.out.println(baseCount.item + "-:-:-");
// return baseCount;
// }
}
return baseCount;
}
Yes, your code (assuming it works; I have not tested it) is O(n * m) in time, and O(n * m) in space.
Complexities cannot be lower than O(n * m), since any cell can be a part of a neighbouring max-basin in the general case, and all must therefore be (in general) examined. Your complexity is O(n * m) due to the two nested for-loops in getMaxBasin, and the fact that visited[i][j] can only be set at a single place (inside scan()), and prohibits later visits of the same cell.
Due to recursion, every time you chain a call scan(), you are adding to the stack. With a sufficiently-long chain of scan() calls, you could run into stack limits. The worst-case scenario is a zig-zag pattern so that the stack ends up containing a scan() call for each an every cell.
I have tested that my partitioning algorithm works well, but when it comes time in the implementation to make use of it, I get an array that is not sorted. Since this is for a class, there's a certain I need to write the class itself so that I can return the answer as string. My problem is most likely in the qkSort() method. Here's the code:
private static int splitterElement;
public static void main (String[] args){
System.out.println(myMethod());
}
public static String myMethod() {
String result = "";
int[] testArray = null;
testArray = populateArray(testArray, 7, 10);
result += "Before sort: \n" + printArray(testArray);
testArray = qkSort(testArray,1,testArray.length);
result += "After sort: \n" + printArray(testArray);
return result;
}
//Method to continually call the partition() method
public static int[] qkSort(int[] x, int left, int right){
if (right - left >= 1) {
//after running this method, the global variable splitterElement is assigned.
x = partition(x,left,right);
qkSort(x,left,splitterElement-1);
qkSort(x,splitterElement + 1,right);
}
//base case. if right-left = 0, then the array length is 1,
//and that is already sorted
return x;
}
/**
* Populates an integer array with random integers. Should be used only with
* non-itialized integer arrays.
*
* #param x an uninitialized array of integers and will be returned once it is populated.
* #param sizeOfArray The size that array x will be initialized to.
* #param rangeOfValues The range of values that that each element can be. This value should
* not surpass the maximum value for integers, but no error-checking is performed.
* #return
*/
public static int[] populateArray (int[] x, int sizeOfArray, int rangeOfValues){
x = new int[sizeOfArray];
for (int i = 0; i < sizeOfArray; i++){
x[i] = (int)(Math.random() * rangeOfValues); //place a random number from 0 to rangeOfValues into array.
}
return x;
}
/**
*
* #param x An integer array. It is assumed that x is initialized when the method is called.
* #param left
* #param right The length of the array can be used for the right int.
* #see #populateArray(int[], int, int)
* #return
*/
public static int[] partition (int[] x, int left, int right){
//element of the splitter
int l = (int) (Math.random() * x.length);
splitterElement = l;
x = swap (x,left,l);
//value of the splitter
int t = x[left];
int i = left;
for (int j = left + 1; j < right; j++){
if (x[j] < t){
i++;
x = swap (x,i,j);
}
}
x = swap(x,left,i);
return x;
}
/**
* Places the value at index1 in index2, and places the value at index2 in index1.
*
* #param array The array that will be worked on.
* #param index1 The first place we will switch values.
* #param index2 The second place we will switch values.
* #return
*/
public static int[] swap (int[] array, int index1, int index2){
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
return array;
}
/**
* A simple print method that prints an array.
* #param array Input.
*/
public static String printArray (int[] array){
String result = "";
for (int i = 0; i < array.length; i++){
result += array[i] + " ";
}
result += "\n";
return result;
}
}
Output:
Before sort:
8 9 7 3 4 2 6
After sort:
8 6 3 9 7 2 4
Thanks for any ideas on what my problem is!
I see several issues in your code:
1) the methods don't need to return the array, you could find a better use for the return value
2) using a global variable splitterElement doesn't work because its value can change during the first recursive call to qkSort. Method partition could return its value instead of returning the array, which is useless.
3) the first line of the partition method:
int l = (int) (Math.random() * x.length);
should be:
int l = left + (int) (Math.random() * (right - left));
because youre partitionning the range between left and right, not the whole array.