How does this recursion make sense? - java

import java.util.*;
public class ArrayList5 {
static int max(ArrayList list) { // to be completed
if (list.size() == 0) {
return 0;
}
else
{
int first = (Integer) list.get(0);
list.remove(0);
if (first > max(new ArrayList(list)))
{
return first;
}
else
{
return max(list);
}
}
}
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList();
Collections.addAll(list, 4, 5, 3, 2, 3, 1, 3);
// int t=Console.readInt("Enter Target:");
int res1 = max(new ArrayList(list));
System.out.println("max=" + res1);
}
}
I don't understand why the max(new ArrayList(list))) part is required. Why does it have to create a new one and why can't it continue to work with the one list?
Also why doesn't it get caught in a loop (it's recursion so it will keep sending up a new list so I don't understand why 'first' isn't going to be 4 every time)?

Actually, there is a lot of superfluous code that is not required and make the code cumbersome/more difficult to read/understand.
You can simplify the code a lot and get rid of any reference to ArrayList which are not really necessary and by using proper generic at the right places, make the code actually readable.
You don't need to cast or create list all over the place.
public class ArrayList5 {
static int max(final List<Integer> list) {
if(list.isEmpty()) return 0;
final int head = list.get(0);
final List<Integer> tail = list.subList(1, list.size());
return (head > max(tail)? head:max(tail));
}
public static void main(final String... args) {
final int res1 = max(Arrays.asList(4, 5, 3, 2, 3, 1, 3));
System.out.printf("max=%d", res1);
}
}

You should try this:
static int max(ArrayList<Integer> list) {...}
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList();
Collections.addAll(list, 4, 5, 3, 2, 3, 1, 3);
// int t=Console.readInt("Enter Target:");
int res1 = max(new ArrayList(list));
System.out.println("max=" + res1);
}
The compiler is probably throws a warning because you don't declare the type of the ArrayList.

Related

Output of List varies while using loops on Varargs

Outputs of the code is varies on iterating with Varargs.
Please let me know what is the reason for different outputs.
public class Demo {
public static void main(String[] args) {
Integer[] a = new Integer[]{1, 2, 3};
Integer[] b = new Integer[]{4, 5, 6};
List<Object> list1=new ArrayList<>();
addAllObj1(list1, a,b);
System.out.println(list1); //[[Ljava.lang.Integer;#24d46ca6, [Ljava.lang.Integer;#4517d9a3]
List<Object> list2=new ArrayList<>();
addAllObj2(list2, a,b);
System.out.println(list2); //[1, 2, 3, 4, 5, 6]
}
private static void addAllObj1(List<Object> list, Object[]... arr) {
for(Object o:arr) {
Collections.addAll(list, o);
}
}
private static void addAllObj2(List<Object> list, Object[]... arr) {
Collections.addAll(list, arr[0]);
Collections.addAll(list, arr[1]);
}
}
Thanks for your Help!
I am sorry for posting a wrong answer, but I think I found the solution now within the Java Specification. Here is how I understand it:
I think the following explains it:
private static void addAllObj2(List<Object> list, Object[]... arr) {
Object o = arr[0];
Collections.addAll(list, o);
Collections.addAll(list, arr[1]);
}
returns:
[[Ljava.lang.Integer;#75a1cd57, 4, 5, 6]
The line with index 1 does work, because during runtime, the jvm evaluates the arity parameters the the type of the input will not be rewritten The conversion to Integer apparently is possible. (I guess the type of b will not be changed)
In the line with index 0, the type will be evaluated and rewritten due to Type Erasure, as it will be stored as the Object o. The Type of the Object o and a (Integer[]) is not the same, therefore erasure takes place and it will be converted to an Object, hence the reference name.
This process apparently only takes place with arity parameters, as without:
public static void main(String[] args) {
List<Object> list3 = new ArrayList<>();
addAllObj3(list3, trePConcat(a, b));
System.out.println(list3);
}
private static void addAllObj3(List<Object> list, Object[] arr) {
Collections.addAll(list, arr[0]);
Collections.addAll(list, arr[1]);
{
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private static Object[] trePConcat(Object[]... arr) {
return arr;
}
returns
[[Ljava.lang.Integer;#75a1cd57, [Ljava.lang.Integer;#3d012ddd]

Java How to return the size of list using recursive function

I am trying to return the size of a list using a recursive function without using .size().
public static int listSize(ArrayList<Integer> lst){
if (lst.isEmpty()){
return 0;
}
return 1 + listSize(lst.remove(0));
}
This is what I have tried to do. When running this code I get an error the .remove(0) does not work at all. Why does the .remove(0) not work within this code?
lst.remove(0)
removes the zero-th element of the list, but it doesn't return a list, it returns the element it removed.
So you instead need to do something like
lst.remove(0);
return 1 + listSize(lst);
One very important thing to keep in mind - you are "destroying" the list being handed to that method. That is not what one would expect when calling a method named listSize() - you would expect two calls to that method (with no intervening changes to the list) to return the same value.
Maybe
public static int listSize(ArrayList<Integer> lst){
if (lst.isEmpty()){
return 0;
}
return 1 + listSize(lst.subList(1, lst.size()));
}
You're just doing it incorrectly. List.remove() doesn't return a list.
List<Integer> a = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
System.out.println(listSize(a));
public static int listSize(List<Integer> lst) {
if (lst.isEmpty()) {
return 0;
}
lst.remove(0);
return 1 + listSize(lst);
}
And here is a version that restores the list by putting the elements back in the correct order.
public static int listSize(List<Integer> lst) {
int b;
if (lst.isEmpty()) {
return 0;
}
b = lst.remove(0);
int v = 1 + listSize(lst);
lst.add(0, b);
return v;
}
To avoid sideEffects one may clone the list while performing the operations
import java.util.*;
public class Main
{
public static void main(String[] args) {
System.out.println("Hello World");
ArrayList<Integer> integerList = new ArrayList();
integerList.add(1);
integerList.add(1);
integerList.add(1);
integerList.add(1);
integerList.add(1);
integerList.add(1);
System.out.println("Length:: " + findListSizeByRecursion(integerList));
}
public static int findListSizeByRecursion(ArrayList<Integer> arrayList){
List<Integer> clonedArrayList = (List<Integer>) arrayList.clone();
if (clonedArrayList.isEmpty()){
return 0;
}
clonedArrayList.remove(0);
return 1 + findListSizeByRecursion((ArrayList<Integer>) clonedArrayList);
}
}

Java Recursion Pass by Reference in ArrayList

I am working on a problem to find which all combinations of integer in a given list can sum up to a given number.
public class SumProblem {
/*
* Input 2-2-3-7
* Output 2+2+3 and 7
*/
public static ArrayList<ArrayList<Integer>> find(ArrayList<Integer> input, int requiredSum) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
find(result, requiredSum, 0, new ArrayList<>(), 0, input);
return result;
}
public static void find(ArrayList<ArrayList<Integer>> result , int requiredSum , int currentSum, ArrayList<Integer> partialResult, int i, ArrayList<Integer> input) {
if (currentSum == requiredSum ) {
ArrayList<Integer> temp = new ArrayList<>();
temp = (ArrayList<Integer>) partialResult.clone();
result.add(temp);
return;
}
if (i >= input.size()) {
return;
}
find(result, requiredSum, currentSum , partialResult, i +1, input );
partialResult.add(input.get(i));
find(result, requiredSum, currentSum + input.get(i) , partialResult, i +1, input );
}
public static void main(String[] args) {
ArrayList<Integer> input = new ArrayList<>();
input.add(2);
input.add(1);
input.add(3);
ArrayList<ArrayList<Integer>> output = find(input, 3);
System.out.println(output.toString());
}
}
I have written code below.
I am facing one problem. In the below line of code, it is adding up all the numbers i traverse even if i create new ArrayList object and assign it to partialResult.
partialResult.add(input.get(i));
Could anyone suggest the solution ?
You have two recursive calls in this dynamic programming solution to the problem. One is supposed to not include the current value in the result, the other does.
You need to make a defensive copy of partialResult, otherwise both recursive calls are going to have a reference to the same list. A list is a mutable object. If both calls get a reference to the same list object, then when you add something to it anywhere, both of them will see the modified list.
The easiest way to make a defensive copy of a list is just to write:
new ArrayList<>(partialResult)
Here is a working version of the program:
import java.util.*;
public class SumProblem {
public static List<List<Integer>> find(List<Integer> input, int requiredSum) {
List<List<Integer>> result = new ArrayList<>();
find(result, requiredSum, 0, new ArrayList<>(), 0, input);
return result;
}
public static void find(List<List<Integer>> result, int requiredSum, int currentSum,
List<Integer> partialResult, int i, List<Integer> input) {
if (currentSum == requiredSum) {
result.add(new ArrayList<>(partialResult)); // add a copy of the list
return;
}
if (i >= input.size()) {
return;
}
// make defensive copies in the recursive calls
find(result, requiredSum, currentSum, new ArrayList<>(partialResult), i + 1, input);
partialResult.add(input.get(i));
find(result, requiredSum, currentSum + input.get(i), new ArrayList<>(partialResult), i + 1, input);
}
public static void main(String[] args) {
List<Integer> input = List.of(2, 8, 2, 3, 4);
List<List<Integer>> output = find(input, 7);
System.out.println(output);
}
}
Output:
[[3, 4], [2, 2, 3]]
I've made a few other changes:
Use List<Integer> and List<List<Integer>> as the types (code to the interface)
Use List.of() to create the input list (added in Java 9)
Don't call toString() on objects passed to println — it's unneeded

PriorityQueue add Element will change the element, weird bug

public class Main {
public static class EE implements Comparable<EE> {
int x;
int[] rac;
public EE(int x, int[] rac) {
this.x = x;
this.rac = rac;
}
public int compareTo(EE that) {
if (this.x != that.x) return this.x - that.x;
else return this.rac[2] = that.rac[2];
}
}
public static void main(String[] args) {
int [][] ary = {
{1,1,3,3},
{1,3,2,4},
{2,3,3,4}};
PriorityQueue<EE> pq = new PriorityQueue<EE>();
for (int[] rec : ary) {
EE e1 = new EE(rec[0], rec);
EE e2 = new EE(rec[2], rec);
pq.add(e1);
pq.add(e2);
}
}
This piece of code I'm running, everything is fine but when the second for loop is entered, rec is [1, 3, 2, 4] initially, when pq.add(e1) get called, value of rec will become [1, 3, 3, 4] anyone can explain why this happens? Thank you in advance!
The preoblem is in comapreTo method:
return this.rac[2] = that.rac[2];
It's returning always the latter that.rac[2]. It should be:
return this.rac[2] == that.rac[2];

Java Calculate all possible combinations of given int array

I am trying to construct a program that would take an array of int({1,2,3} and a length value and calculate all possible combinations of this array.
For example:
int[] arr= new char[] {0,1};
int[] tes = new int[3];
possiblecomb(2, arr,tes,0);
This will output:
00
10
01
11
But i keep getting a Stack overflow error when i try to call the possiblecomb in the for loop
import java.util.Arrays;
public class Program {
public static void main(String[] args) {
// Create an arr to work with
int[] test = new int[] {0,1};
int[] tes = new int[3];
// Find all possible combinations of this arr in the string size of 3
possiblecomb(3, test,tes,0);
}
public static void possiblecomb(int maxLength, int[] nums, int[] curr,int end) {
// If the current array has reached it's maximum length
if(end == maxLength) {
System.out.println(Arrays.toString(curr));
// Else add each number from the numbs to new array and process these new arrays again
} else {
for(int i = 0; i < nums.length; i++) {
int[] oldCurr = curr.clone();
curr[end]= nums[i];
possiblecomb(maxLength,nums,curr,end++);
curr = oldCurr.clone();
}
}
}
}
Try moving your recursive call outside of the for.
You are using the for in order to copy contents.
Your end variable will eventually increment above max lenght, and your (==) comparison won't be a stopper.
Take the example where num.Length = 2 and end is 2 :
You will call your function once with end = 3 which will stop and print inside the recursive call, and next, when i == 1 your end will be 4 and the recursive call won't break.
If you want to avoid the infinite recurssion with your current code in order to better debug with output, put the break condition
if (end>=maxLength)
As #MichaelCMS said you never stop the recursion, hence a stack overflow.
If you don't mind using Lists instead of arrays this is a solution:
import java.util.*;
public class Program {
private static List<List<Integer>> combinations(List<Integer> list, int maxLength) {
return combinations(list, maxLength, new ArrayList(), new ArrayList());
}
private static List<List<Integer>> combinations(List<Integer> list, int length, List<Integer> current, List<List<Integer>> result) {
if (length == 0) {
List<List<Integer>> newResult = new ArrayList<>(result);
newResult.add(current);
return newResult;
}
List<List<List<Integer>>> res3 = new ArrayList<>();
for (Integer i : list) {
List<Integer> newCurrent = new ArrayList<>(current);
newCurrent.add(i);
res3.add(combinations(list, length - 1, newCurrent, result));
}
List<List<Integer>> res2 = new ArrayList<>();
for (List<List<Integer>> lst : res3) {
res2.addAll(lst);
}
return res2;
}
public static void printCombinations(List<Integer> list, int maxLength) {
List<List<Integer>> combs = combinations(list, maxLength);
for (List<Integer> lst : combs) {
String line = "";
for (Integer i : lst) {
line += i;
}
System.out.println(line);
}
}
public static void main(String[] args) {
List<Integer> l = Arrays.asList(0, 1);
printCombinations(l, 2);
}
}
That gives you:
00
01
10
11

Categories

Resources