Avoid repeating arrays in random permutations in java - java

I have the following code:
public static void nextPermutationArray(int[] v) {
int x = 1;
int y;
Random r = new Random();
while (x < v.length) {
y = x + r.nextInt(v.length - x);
int temp = v[x];
v[x] = v[y];
v[y] = temp;
x++;
}
}
public static void main(String[] args) {
int[] a = new int[]{0, 1, 2, 3};
nextPermutationArray(a);
System.out.println(Arrays.toString(a));
nextPermutationArray(a);
System.out.println(Arrays.toString(a));
nextPermutationArray(a);
System.out.println(Arrays.toString(a));
nextPermutationArray(a);
System.out.println(Arrays.toString(a));
}
The program returns me:
0321
0231
0231
0132
My question is: is there any way to edit the method nextPermutationArray to avoid random permutations like 0231. In other words, the method should return 4 unrepeatable elements.

You can store each permutation that has already been returned in a static variable of type int[][]. If you get a result that is already in the array, you can make another permutation. Repeat until you have a new permutation. But be careful, this can make an endless loop if you want to produce more permutations than possible!

This should print out all the permutation without storing them in a HashMap or a List
public static boolean nextPermutationArray(int[] a) {
int i = a.length - 2;
while (i >= 0 && a[i] >= a[i + 1]) {
i--;
}
if (i < 0) {
return false;
}
int j = a.length - 1;
while (a[i] >= a[j]) {
j--;
}
int t = a[i];
a[i] = a[j];
a[j] = t;
Collections.reverse(Arrays.asList(Arrays.copyOfRange(a, i + 1, a.length)));
return true;
}
it will return true until there is a premutation to use it run this code
public static void main(String[] args) {
int[] a = new int[]{0, 1, 2, 3};
do {
System.out.println(Arrays.toString(a));
} while (nextPermutationArray(a));
}
output is
[0, 1, 2, 3]
[0, 1, 3, 2]
[0, 2, 3, 1]
[0, 3, 2, 1]
[1, 3, 2, 0]
[2, 3, 1, 0]
[3, 2, 1, 0]

Related

How can I get the subset from an ArrayList?

I'm working on a problem that asks me to "Write a method that returns all of the subsets of the set formed by the integers 1 to N where N is passed to the method." If I pass N = 3 to the method my output should look like [[0], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]. My current output is [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]. Is there a way for me to print out the desired range like doing Arrays.copyOfRange() for the ArrayList? or is there another way of getting the subset with my desired output?;
import java.util.ArrayList;
import java.util.HashSet;
public class HW3 {
public static void main(String[] args) {
System.out.println(powerset(3));
}
public static ArrayList<HashSet<Integer>> powerset(int N) {
ArrayList<HashSet<Integer>> arrayList = new ArrayList<HashSet<Integer>>();
HashSet<Integer> arrayListNew = new HashSet<Integer>();
for (int i = 0; i <= N; i++)
arrayListNew.add(i);
for (int i = 0; i < (int) Math.pow(2, N); i++)
arrayList.add(arrayListNew);
return arrayList;
}
}
"Is there a way for me to print out the desired range like doing Arrays.copyOfRange() for the ArrayList?"
yes, use sublist() read more here
However, you don't need that for your question. The algorithm you are looking for should look sth like this
//1st for loop iterate through all the possible sizes for the hash set
for(){
//2nd for loop generate all possible combinations given the size
for(){
}
}
//might need to add the [0] urself at the end
public class HW3 {
static void printSubsets(int set[]) {
int n = set.length;
for (int i = 0; i < (1 << n); i++) {
System.out.print("{ ");
for (int j = 0; j < n; j++)
if ((i & (1 << j)) > 0)
System.out.print(set[j] + " ");
System.out.println("}");
}
}
public static void main(String[] args) {
int n = 3;
int[] set = new int[n+1];
for(int i = 0; i<=n; i++){
set[i]=i;
}
printSubsets(set);
}}
The total number of subsets of any given set is equal to 2^ (no. of elements in the set). If we carefully notice it is nothing but binary numbers from 0 to 7 which can be shown as below:
000
001
010
011
100
101
110
111
Starting from right, 1 at ith position shows that the ith element of the set is present as 0 shows that the element is absent. Therefore, what we have to do is just generate the binary numbers from 0 to 2^n – 1, where n is the length of the set or the numbers of elements in the set.
Time complexity: O(n * (2^n)) as the outer loop runs for O(2^n) and the inner loop runs for O(n).
The more suitable way to do this is Backtracking
public class BacktrackTest {
public static void main(String[] args) {
powerset(3);
}
public static void powerset(int num) {
if (num >= 10 || num < 1) {
throw new IllegalArgumentException();
}
int[] chs = new int[num];
for (int i = 1; i <= num; i++) {
chs[i - 1] = i;
}
List<List<Integer>> resultList = new ArrayList<>();
backtrack(0, chs, new ArrayList<>(), resultList);
Collections.sort(resultList, (a, b) -> {
int len1 = a.size();
int len2 = b.size();
return len1 - len2;
});
System.out.println(resultList);
}
public static void backtrack(int index, int[] chs, List<Integer> tempList, List<List<Integer>> resultList) {
for (int i = index; i < chs.length; i++) {
tempList.add(chs[i]);
resultList.add(new ArrayList<>(tempList));
backtrack(i + 1, chs, tempList, resultList);
tempList.remove(tempList.size() - 1);
}
}
}
Java Fiddle Demo
Output result:

Remove an element from array and replace with 0?

public static void remove (int[] arr, int toRemove)
"It should remove the value toRemove from the array. The remaining elements should just be shifted toward the beginning of the array. (The array's size will not change). Since the array will now have one fewer element in use, the original last element should just be replaced with 0. If there is more than one occurrence of toRemove in the array, only the FIRST occurrence should be removed. If the array has no elements, it should just have no effect".
So far, I have this:
public static void remove(int[] arr, int toRemove) {
for(int i = 0; i <= arr.length - 1; i++) {
if(arr[i] == toRemove) {
arr[i] = arr[i + 1];
arr[toRemove] = 0;
}
}
}
I have a main method with an array with its contents: [3, 5, 7, 8, 12, 2] and a call saying remove(array, 5). However, my array prints out [3, 7, 7, 8, 12, 0], when it should print out [3, 7, 8, 12, 2, 0].
Can someone let me know what I have wrong and explain it?
Here is an approach, similar to what I described in the comments above.
import java.util.Arrays;
public class main
{
// tip: arguments are passed via the field below this editor
public static void main(String[] args)
{
int[] arr = {3, 5, 7, 8, 5, 12, 2};
remove(arr, 5);
System.out.println(Arrays.toString(arr)); // [3, 7, 8, 5, 12, 2, 0]
}
public static void remove(int[] arr, int toRemove) {
int idx = -1;
// determine first occurrence of toRemove
for(int i = 0; i < arr.length; i++) {
if(arr[i] == toRemove) {
idx = i;
break;
}
}
// if not found, return
if(idx == -1) return;
// shift other elements down
for(int i = idx; i < arr.length-1; i++) {
arr[i] = arr[i+1];
}
// set last element to 0
arr[arr.length-1] = 0;
}
}
You need to have two indexes:
fromIndex is the one that go on the array.
toIndex is the place that the item need to be.
public static void remove(int[] arr, int toRemove) {
int toIndex = 0;
for(int fromIndex = 0; fromIndex < arr.length; fromIndex++) {
//paste number only if its not 'toRemove'
if(arr[fromIndex] != toRemove) {
arr[toIndex] = arr[fromIndex];
toIndex++;
}
}
//Fill the rest with 0
for (; toIndex < arr.length; toIndex++)
arr[toIndex] = 0;
}
this works if there are multiple indexes with the value of toRemove
You should use System.arraycopy. It's fast.
Try this.
public static void remove(int[] arr, int toRemove) {
for(int i = 0, length = arr.length; i < length; i++) {
if(arr[i] == toRemove) {
System.arraycopy(arr, i + 1, arr, i, length - i - 1);
arr[length - 1] = 0;
break;
}
}
}
public static void main(String[] args) throws IOException {
int[] a0 = {0, 1, 2, 3, 4};
remove(a0, 0);
System.out.println(Arrays.toString(a0));
int[] a4 = {0, 1, 2, 3, 4};
remove(a4, 4);
System.out.println(Arrays.toString(a4));
int[] a5 = {0, 1, 2, 3, 4};
remove(a5, 5);
System.out.println(Arrays.toString(a5));
int[] a6 = {0};
remove(a6, 0);
System.out.println(Arrays.toString(a6));
int[] a7 = {};
remove(a7, 0);
System.out.println(Arrays.toString(a7));
}
output:
[1, 2, 3, 4, 0]
[0, 1, 2, 3, 0]
[0, 1, 2, 3, 4]
[0]
[]

Can't figure out what is wrong with my merge sort code

I went over it multiple times and I am not sure what I am doing wrong.
he logic seems OK but it is printing out the first number only. I left out the main method:
public class MergeSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] bob = {4,7,99,8,12,6};
Mergesort(bob);
for(int i=0; i< bob.length; i++){
System.out.print(bob[i]+",");
}
}
public static int[] Mergesort(int[] bob){
int length = bob.length;
int mid = bob.length/2;
if(length <= 1){
return bob;
}
int[] left = new int[mid];
int[] right = new int[length-left.length];
for(int i=0; i< mid; i++){
left[i]=bob[i];
}
for(int j=mid; j< length; j++){
right[j-mid]=bob[j];
}
Mergesort(left);
Mergesort(right);
merge(left,right, bob);
return bob;
}
//this is merge method
public static int[] merge(int[] left, int[] right, int[] bob){
int l= left.length;
int r = right.length;
int i=0, j=0,k=0;
while(i<l && j<r){
if(left[i]<=right[j]){
bob[k] = left[i];
i++;
}
else
{
bob[k] = right[j];
j++;
}
k++;
}
while(i<l){
bob[k] = left[i];
i++;
k++;
}
while(j<r){
bob[k] = bob[j];
j++;
k++;
}
return bob;
}
}
Rather than just tell you the answer, I'm going to show you how to quickly figure it out via test/debug. You know, "teach a man to fish" and all that (source).
So, let's test your merge method. I've modified the main method to only merge two sorted arrays {1, 3, 5} and {2, 4, 6}. We know that the output should be {1, 2, 3, 4, 5, 6}.
At the same time, let's debug as well. The most primitive way to debug is known as "printf debugging," meaning we just put lots of logging statements in the code so that we can see what the internal state is at every step. I've added logging wherever your merge output array is modified. The goal is to observe the moment it is modified in an incorrect/unexpected way.
Here's the code with these two modifications:
public class MergeSort {
public static void main(String[] args) {
int[] left = {1, 3, 5};
int[] right = {2, 4, 6};
int[] merged = {0, 0, 0, 0, 0, 0};
merge(left, right, merged);
}
public static int[] merge(int[] left, int[] right, int[] bob) {
System.out.print("Before merge: ");
System.out.println(Arrays.toString(bob));
int l = left.length;
int r = right.length;
int i = 0, j = 0, k = 0;
while (i < l && j < r) {
if (left[i] <= right[j]) {
bob[k] = left[i];
System.out.print("Merge step 1: ");
System.out.println(Arrays.toString(bob));
i++;
} else {
bob[k] = right[j];
System.out.print("Merge step 2: ");
System.out.println(Arrays.toString(bob));
j++;
}
k++;
}
while (i < l) {
bob[k] = left[i];
System.out.print("Merge step 3: ");
System.out.println(Arrays.toString(bob));
i++;
k++;
}
while (j < r) {
bob[k] = bob[j];
System.out.print("Merge step 4: ");
System.out.println(Arrays.toString(bob));
j++;
k++;
}
return bob;
}
}
And here is the output:
Before merge: [0, 0, 0, 0, 0, 0]
Merge step 1: [1, 0, 0, 0, 0, 0]
Merge step 2: [1, 2, 0, 0, 0, 0]
Merge step 1: [1, 2, 3, 0, 0, 0]
Merge step 2: [1, 2, 3, 4, 0, 0]
Merge step 1: [1, 2, 3, 4, 5, 0]
Merge step 4: [1, 2, 3, 4, 5, 3]
So, where is the problem in your code? Clearly in "merge step 4," or the line bob[k] = bob[j];. How cool is that? With a few simple print calls, we've located the exact line of your bug!
I believe your bug is in this line in merge():
bob[k] = bob[j];
It should be
bob[k] = right[j];
With this change I get this output:
4,6,7,8,12,99,

Sort and rearrange (distinct) arrays

I have two int[] arrays I and J as follows:
int[] I = { 1, 2, 4, 5, 3 };
int[] J = { 8, 7, 6, 3, 2 };
I want to sort I, and then rearrange J using the same indices so the two arrays stay in registration. The result should be:
I = { 1, 2, 3, 4, 5 };
J = { 8, 7, 2, 6, 3 };
I would start by writing a routine to swap elements in an int[]. Something like,
public static void swap(int[] arr, int i, int j) {
if (i == j) {
return;
}
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
Then you could use it and Arrays.toString(int[]) and something like
public static void main(String[] args) {
int[] I = { 1, 2, 4, 5, 3 };
int[] J = { 8, 7, 6, 3, 2 };
for (int i = 0; i < I.length - 1; i++) {
for (int j = i + 1; j < I.length; j++) {
if (I[i] > I[j]) {
swap(I, i, j);
swap(J, i, j);
}
}
}
System.out.printf("I = %s%n", Arrays.toString(I));
System.out.printf("J = %s%n", Arrays.toString(J));
}
Output is (as requested)
I = [1, 2, 3, 4, 5]
J = [8, 7, 2, 6, 3]
This can also be accomplished with Java 8 IntStream and additional Pair class representing a 2-tuple (I know, it's a bit ugly because we have to copy the values back to the array):
public class Main {
public static void main(String[] args) {
final int[] I = {1, 2, 4, 5, 3};
final int[] J = {8, 7, 6, 3, 2};
List<Pair> pairs = IntStream.range(0, I.length)
.mapToObj(n -> new Pair(I[n], J[n]))
.sorted((p1, p2) -> p1.i - p2.i)
.collect(Collectors.toList());
for (int k=0; k < pairs.size(); k++) {
Pair p = pairs.get(k);
I[k] = p.i;
J[k] = p.j;
}
System.out.println(Arrays.toString(I));
System.out.println(Arrays.toString(J));
}
public static class Pair {
public int i,j;
public Pair(int i, int j) {
this.i = i;
this.j = j;
}
}
}
Output:
[1, 2, 3, 4, 5]
[8, 7, 2, 6, 3]
Keeping the arrays in sync isn't very pretty, I would strongly suggest to model this properly by using an array of tuple objects instead. Then, it's much simpler:
public class Main {
public static void main(String[] args) {
final Pair[] P = {new Pair(1,8), new Pair(2,7), new Pair(4,6),
new Pair(5,3), new Pair(3,2)};
Arrays.sort(P, (p1, p2) -> p1.i - p2.i);
System.out.println(Arrays.toString(P));
}
public static class Pair {
public int i,j;
public Pair(int i, int j) {
this.i = i;
this.j = j;
}
#Override
public String toString() {
return String.format("(%d, %d)", i, j);
}
}
}
Output:
[(1, 8), (2, 7), (3, 2), (4, 6), (5, 3)]
As #ajb has noted in the comments above, the easiest way to implement this is to use a class modelling a tuple.
This has the advantage that you can use the Arrays.sort builtin which saves you from writing your own sorting algorithm. On the other hand, there is the additional overhead of transferring data from the Tuples to the raw arrays.
However, you may find that in your application you are able to directly use the Tuple objects without transferring them back to arrays.
import java.util.*;
class Tuple implements Comparable<Tuple>
{
int x;
int y;
Tuple(int a, int b)
{
x = a;
y = b;
}
public int compareTo(Tuple another)
{
return Integer.compare(x, another.x);
}
}
class Main
{
public static void main(String args[])
{
int a[] = {1, 2, 4, 5, 3};
int b[] = {8, 7, 6, 3, 2};
Tuple arr[] = new Tuple[a.length];
for (int i=0;i<a.length;i++)
arr[i] = new Tuple(a[i], b[i]);
Arrays.sort(arr);
for (int i=0;i<a.length;i++)
{
a[i] = arr[i].x;
b[i] = arr[i].y;
}
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
}
}
And the output:
[1, 2, 3, 4, 5]
[8, 7, 2, 6, 3]

Pushing Integer array to ArrayList

I got stuck in very basic way of pushing sequence of Integer-array to arraylist.
I am trying alter the solution of polygenelubricants for the question K Combinations of set of Integers such that instead of printing them, I am pushing them to an array list.
My code:
public class Test {
static ArrayList<String> combinations;
public static void main(String args[]) {
Integer[] a3 = { 1, 2, 3, 4, 5 };
comb(a3, 2);
}
public static void comb(Integer[] items, int k) {
Arrays.sort(items);
combinations = new ArrayList<String>();
ArrayList<String> c1 = new ArrayList<String>();
c1 = kcomb(items, 0, k, new Integer[k]);
System.out.println("from comb");
for (String x : c1) {
System.out.println(x);
}
}
public static ArrayList<String> kcomb(Integer[] items, int n, int k,
Integer[] arr) {
if (k == 0) {
combinations.add(Arrays.toString(arr));
} else {
for (int i = n; i <= items.length - k; i++) {
arr[arr.length - k] = items[i];
kcomb(items, i + 1, k - 1, arr);
}
}
return combinations;
}
}
Output:
from comb
[1, 2]
[1, 3]
[1, 4]
[1, 5]
[2, 3]
[2, 4]
[2, 5]
[3, 4]
[3, 5]
[4, 5]
But When I changed the type of ArrayList from String to Integer[] as follows, I am getting redundant output.
Changed Code
public class Test {
static ArrayList<Integer[]> combinations;
public static void main(String args[]) {
Integer[] a3 = { 1, 2, 3, 4, 5 };
comb(a3, 2);
}
public static void comb(Integer[] items, int k) {
Arrays.sort(items);
combinations = new ArrayList<Integer[]>();
ArrayList<Integer[]> c1 = new ArrayList<Integer[]>();
c1 = kcomb(items, 0, k, new Integer[k]);
System.out.println("from comb");
for (Integer[] x : c1) {
System.out.println(Arrays.toString(x));
}
}
public static ArrayList<Integer[]> kcomb(Integer[] items, int n, int k,
Integer[] arr) {
if (k == 0) {
combinations.add(arr);
} else {
for (int i = n; i <= items.length - k; i++) {
arr[arr.length - k] = items[i];
kcomb(items, i + 1, k - 1, arr);
}
}
return combinations;
}
}
Output:
from comb
[4, 5]
[4, 5]
[4, 5]
[4, 5]
[4, 5]
[4, 5]
[4, 5]
[4, 5]
[4, 5]
[4, 5]
Can someone help me to point out what am I doing wrong...
Thanks,
Sarath
public class Test {
static ArrayList<Integer[]> combinations;
public static void main(String args[]) {
Integer[] a3 = { 1, 2, 3, 4, 5 };
comb(a3, 2);
}
public static void comb(Integer[] items, int k) {
Arrays.sort(items);
combinations = new ArrayList<Integer[]>();
ArrayList<Integer[]> c1 = new ArrayList<Integer[]>();
c1 = kcomb(items, 0, k, new Integer[k]);
System.out.println("from comb");
for (Integer[] x : c1) {
System.out.println(Arrays.toString(x));
}
}
public static ArrayList<Integer[]> kcomb(Integer[] items, int n, int k,
Integer[] arr) {
if (k == 0) {
combinations.add(arr);
} else {
for (int i = n; i <= items.length - k; i++) {
Integer[] arr1 = new Integer[arr.length];
System.arraycopy(arr, 0, arr1, 0, arr.length);
arr1[arr.length - k] = items[i];
kcomb(items, i + 1, k - 1, arr1);
}
}
return combinations;
}
}
There is your error: combinations.add(arr); you are working always on the same array arr.
Keep in mind, arrays are objects and have a reference. You save the same array arr reference to the ArrayList and keep changing the array values afterwards. You always get the value of the last combination for all other combinations as you are working on the same array every time.
Therefore, you need to clone arr before you add it to the ArrayList in order to obtain a new reference. The code was working before as every String has its own reference as Strings are immutable.
the problem is that you are only ever creating one Integer[] array - it is being reused for each call to kcomb, so at the end of the process the same array has been added multiple times to the list, but the contents of the array is only the last combination. Also, you don't need to use Integer[] for this purpose - int[] is quite satisfactory and more efficient.

Categories

Resources