static List<List<Integer>> finalSubset = new ArrayList<>();
public static void main(String[] args) {
ArrayList<Integer> a = new ArrayList<>();
Integer[] array = {1, 2 ,3};
Collections.addAll(a, array);
subsets(a, 0);
System.out.println(finalSubset);
}
static void subsets (ArrayList<Integer> arr, int pos) {
if (arr.size() == 0) return;
finalSubset.add(arr); //problem
for (int i = pos; i < arr.size(); i++) {
Integer temp = arr.get(i);
arr.remove (i);
subsets(arr, i);
arr.add(i, temp);
}
}
I've tried out to make a code that prints out all possible subsets of given array using ArrayList and when I run it output is correct, but when I substitute System.out.println(arr) by funalSubset.add(arr) the output is:
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
when it needs to be:
[1, 2, 3], [2, 3], [3], [2], [1, 3], [1], [1, 2], []
what's the reason of such output?
You are adding the same array list to finalSubset many times. You should create a copy every time you recurse, either when you add to finalSubset:
finalSubset.add(new ArrayList<>(arr));
OR when you do the recursive call:
subsets(new ArrayList<>(arr), i);
This way you have different lists that can have different things inside. If you only have one list, you just get the same thing repeated 8 times.
Also, you should add to finalSubset before you return, otherwise the empty list won't be added to finalSubset.
finalSubset.add(new ArrayList<>(arr));
if (arr.size() == 0) return;
Related
It's a combinatorics problem. We can partition the array at max n-1 times and out of it, we have to choose k-1 partitions.
Ex: arr[] = {1, 2, 3, 4, 5, 6}
k = 3, n = 6.
Total possibilities = (n-1)C(k-1) 5C2 = 10.
Expected Output : (3-dimensional array)
[
[[1], [2], [3, 4, 5, 6]],
[[1], [2, 3], [4, 5, 6]],
[[1], [2, 3, 4], [5, 6]],
[[1], [2, 3, 4, 5], [6]],
[[1, 2], [3], [4, 5, 6]],
[[1, 2], [3, 4], [5, 6]],
[[1, 2], [3, 4, 5], [6]],
[[1, 2, 3], [4, 5], [6]],
[[1, 2, 3, 4], [5], [6]],
]
Constraints:
Subarrays should have at least 1 element.
SubArrays should only consist of consecutive elements.
For ex: [[1, 3], [2, 4], [5, 6]] This is not valid.
So far, I have tried a recursive method but it yields wrong results. I can't wrap my head around how to correct it. I need an answer explaining how to approach this problem properly and the intuition behind it first and then correct my code and point out where I went wrong.
My code:
public static void main(String[] args) {
int n = 6;
int k = 3;
int[] arr = new int[]{1,2,3,4,5,6};
ArrayList<ArrayList<ArrayList<Integer>>> result = new ArrayList<ArrayList<ArrayList<Integer>>>();
ArrayList<ArrayList<Integer>> eachComb = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> eachSubArray = new ArrayList<Integer>();
int index = 0;
generateCombinations(arr, k, index, eachSubArray, eachComb, result);
for (ArrayList<ArrayList<Integer>> each : result) {
for(ArrayList<Integer> eachh: each) {
System.out.println(eachh);
}
System.out.println("-------------------------------");
}
}
private static void generateCombinations(int[] arr, int k, int index, ArrayList<Integer> eachSubArray,
ArrayList<ArrayList<Integer>> eachComb, ArrayList<ArrayList<ArrayList<Integer>>> result) {
if(k==0 || index==arr.length) {
return;
}
if(!eachSubArray.isEmpty()) {
eachComb.add(new ArrayList<>(eachSubArray));
}
if(k==1) {
ArrayList<Integer> last = new ArrayList<Integer>();
for(int i=index; i<arr.length; i++) {
last.add(arr[i]);
}
if(!last.isEmpty()) {
eachComb.add((last));
result.add(new ArrayList<ArrayList<Integer>>(eachComb));
eachComb.remove(eachComb.size()-1);
}
return;
}
eachSubArray.clear();
for(int i=index; i<arr.length; i++) {
eachSubArray.add((arr[i]));
generateCombinations(arr, k-1, i+1, eachSubArray, eachComb, result);
if(!eachComb.isEmpty()) {
eachComb.remove(eachComb.size()-1);
}
}
}
I am creating unique subsequences of size 2 using below code. How can I create subsequences of different sizes. Size would be dynamic.
For example, [1 2 3 4] -> [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
For size 3, it would be , [[1, 2, 3], [1, 2, 4], [2, 3, 4]]
public static int getTheSubseq(List<Integer> AList){
List<List<Integer>> li = new ArrayList<>();
for (int i = 0; i < AList.size(); i++){
for(int j =i+1; j < AList.size(); j++){
List<Integer> temp = new ArrayList<>();
temp.add(AList.get(i));
temp.add(AList.get(j));
li.add(temp);
}
}
System.out.println(li);
return 1;
}
Using recursion you could build the subsequences as follows:
private void buildSubsequence( List<Integer> source, int targetSize,
List<List<Integer>> result, Stack<Integer> currentSubsequence, int currentIndex ) {
//We don't want to iterate beyond the point where we can't build a complete subsequence.
//Thus we'll need to subtract the number of still needed elements
//(target count - number of elements already in the subsequence - 1 for this call)
int maxIndex = source.size() - ( targetSize - currentSubsequence.size() - 1);
//iterate over each index from the current one to this call's max
for( int i = currentIndex; i < maxIndex; i++ ) {
//add the element at that index to the subsequence
currentSubsequence.push( source.get( i ) );
//if we're done make a copy
if( currentSubsequence.size() == targetSize ) {
result.add( new ArrayList<Integer>( currentSubsequence) );
} else { //if we're not done, get the next element
buildSubsequence( source, targetSize, result, currentSubsequence, i + 1 );
}
//remove the last element added by push() to have it replaced with the next one
currentSubsequence.pop();
}
}
Then you call it like this:
List<Integer> source = Arrays.asList( 1,2,3,4,5,6 );
List<List<Integer>> result = new LinkedList<>();
buildSubsequence( source, 3, result, new Stack<>(), 0 );
That creates the following subsequences:
[1, 2, 3]
[1, 2, 4]
[1, 2, 5]
[1, 2, 6]
[1, 3, 4]
[1, 3, 5]
[1, 3, 6]
[1, 4, 5]
[1, 4, 6]
[1, 5, 6]
[2, 3, 4]
[2, 3, 5]
[2, 3, 6]
[2, 4, 5]
[2, 4, 6]
[2, 5, 6]
[3, 4, 5]
[3, 4, 6]
[3, 5, 6]
[4, 5, 6]
Note that this is just one way to solve it. :)
This question already has answers here:
Why does my ArrayList contain N copies of the last item added to the list?
(5 answers)
Closed 4 years ago.
I am trying to save a list of permutations to use later in my program. However, when I try to append the permutation results to full_list, the original list gets saved to the list over and over. BUT the results printed from System.out.println(arr); are exactly what I want.
import java.util.*;
public class mytest {
public static void main(String[] args){
ArrayList<Integer> inlist = new ArrayList<Integer>();
inlist.add(1);
inlist.add(2);
inlist.add(3);
permute(inlist, 0);
System.out.println(full_list);
}
public static HashSet<ArrayList<Integer>> full_list = new HashSet<ArrayList<Integer>>();
public static void permute(ArrayList<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(arr);
full_list.add(arr);
}
}
}
results from System.out.println(arr);
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 2, 1]
[3, 1, 2]
results from printing full_list in the main method:
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
What can I do to fix this so the printed results are saved in the full_list?
You are changing values of arr that are adding to full_list. To prevent this you should add new clone of arr to full_list:
full_list.add(new ArrayList<>(arr));
Just do: full_list.add(new ArrayList<Integer>(arr));
The error in your code is that you are adding the same ArrayList every time, but you have to create a copy of it. This code is creating a copy new ArrayList<Integer>(arr)
import java.util.*;
public class RotateList {
public static void main(String[] args)
{
List<List<Integer>> copies = new ArrayList<>();
List<Integer> list = new ArrayList<>(Arrays.asList(1,2,3));
int size = list.size();
Set<List<Integer>> set = new HashSet<>();
while(size > 0)
{
copies.add(list);
size--;
}
size = list.size();
System.out.println("Copies Before:");
System.out.println(copies);
for(int i = 0; i < copies.size();i++)
{
Collections.rotate(copies.get(i), i+1);
}
System.out.println("Copies after:");
System.out.println(copies);
}
}
The output is:
Copies Before: [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
Copies after: [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
I don't know where I'm going wrong with this.
The problem is that you are adding the same list 3 times. When you rotate one of them, you rotate all of them.
You must create 3 separate lists.
List<List<Integer>> copies = new ArrayList<>();
for(int i = 0; i < 3; i++) {
copies.add(new ArrayList<>(Arrays.asList(1,2,3)));
}
System.out.println("Copies Before:");
System.out.println(copies);
for (int i = 0; i < copies.size(); i++) {
Collections.rotate(copies.get(i), i + 1);
}
System.out.println("Copies after:");
System.out.println(copies);
Output:
Copies Before:
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
Copies after:
[[3, 1, 2], [2, 3, 1], [1, 2, 3]]
I'm a beginner in programming and I have a method :
public int[][] toArray(List<Integer> list, int rows) {
int[][] result = new int[list.size()][rows];
int i = 0;
int j = 0;
for (Integer value : list) {
result[i][j] = value;
j++;
if(j > rows - 1){
i++;
j = 0;
}
}
return result;
}
The result of it, if rows = 2 (and if we have a list contains numbers from 1 to 7) is:
[[1, 2], [3, 4], [5, 6], [7, 0], [0, 0], [0, 0], [0, 0]]
If rows = 3 result is:
[[1, 2, 3], [4, 5, 6], [7, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
What I need:
[[1, 2], [3, 4], [5, 6], [7, 0]]
[[1, 2, 3], [4, 5, 6], [7, 0, 0]]
How to do that?
Just for fun, here's another approach using Streams and Guava:
public static int[][] toArray(List<Integer> list, int rows) {
return Lists.partition(list, rows)
.stream()
.map(Ints::toArray)
.map(a -> Arrays.copyOf(a, rows))
.toArray(int[][]::new);
}
The problem lies in this line of code:
int[][] result = new int[list.size()][rows];
As you are initializing the result to a 2D array having rows equals to list.size() you are getting always seven rows. The solution is to first compute the number of rows for result array properly and then initialize it.
int resultRows = list.size()/rows;
if(list.size()%rows!=0){
resultRows++;
}
int[][] result = new int[resultRows][rows];
You can use a counter to track the count and determine the position by counter/rows and counter%rows, e.g.:
public int[][] toArray(List<Integer> list, int rows) {
int[][] result = new int[list.size()][rows];
int counter = 0;
for (Integer value : list) {
result[counter/rows][counter%rows] = value;
counter++;
}
return result;
}
You don't need to worry about remaining places as all the MxN elements get initialised with 0 when you declare an array with size.