Return values from recursion - java

Could someone please help me with the recursion code below?
Given an input array and a target, I want to return a boolean true for any nonempty subset which sums up to the target value. I am confused about how to return the correct boolean value from recursion.
In my approach below, I am summing up all the possible combinations of a non-empty sub-set and want to return True to the calling function if any of the non-empty subsets equals the target value. The issue is, due to the multiple recursive call stacks, the correct/expected value for the boolean for a sub-set gets overwritten by the subsequent/remaining recursive call stacks. Is there a work-around for this issue? Or do I use brute force? where-in I store all the possible boolean values for each sub-set combination in a list and return true if atleast one value in the list is a boolean True?
public class RecursionPossibleToAchieveTargetSum {
public static void main(String[] args ) {
long[] arr = {4,8};
long k = 4;
boolean flag = false;
if (arr.length > 0 )
flag = recursionHelper(arr,0,new long[arr.length],0, k);
System.out.println(flag);
}
public static Boolean recursionHelper(long[] arr, int spos, long[] temp, int tempIndex, long target) {
if ( spos == arr.length ) {
return (recursiveAddition(temp, temp.length - 1) == target);
}
recursionHelper(arr, spos + 1, temp, tempIndex, target );
temp[tempIndex] = arr[spos];
return recursionHelper(arr, spos + 1, temp, tempIndex + 1, target);
}
public static long recursiveAddition(long[] arr, int spos) {
if ( spos == 0 ) {
return arr[spos];
} else {
return arr[spos] + recursiveAddition(arr, spos-1);
}
}
}

You can use a List<long[]> to save all the subsets that add up to the target. I also cleaned up the recursion a bit. You can check the size of this result list with "result.size() > 0" and print that boolean. You can also print each array of subsets to know which ones there are.
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
public class RecursionPossibleToAchieveTargetSum {
public static void main(String[] args ) {
long[] arr = {1,2,4,1,3,5};
long target = 8;
List<long[]> result = new ArrayList<long[]>();
if (arr.length > 0 ) {
result = recursionHelper(arr, target);
}
System.out.println(result.size() > 0);
for(long[] l : result) {
System.out.println(Arrays.toString(l));
}
}
public static List<long[]> recursionHelper(long[] arr, long target) {
List<long[]> result = new ArrayList<long[]>();
if (arr.length == 0) return result;
for(int j = arr.length; j > 0; --j) {
long nextsom = recursiveAddition(Arrays.copyOfRange(arr, 0, j));
if (nextsom == target) result.add(Arrays.copyOfRange(arr, 0, j));
}
result.addAll(recursionHelper(Arrays.copyOfRange(arr, 1, arr.length), target));
return result;
}
public static long recursiveAddition(long[] arr) {
if ( arr.length == 1 ) return arr[0];
return arr[0] + recursiveAddition(Arrays.copyOfRange(arr, 1, arr.length));
}
}
Example output with arr = {1,2,4,1,3,5} and target = 8:
true
[1, 2, 4, 1]
[4, 1, 3]
[3, 5]

Related

Count occurrences of a given integer in an array using recursion

Without using a loop, I'm trying to count the number of times a given integer is in an array using recursion. I keep getting a StackOverflow error and I can't figure out why.
public static int countOccurrences(int[] arr, int n) {
if (arr.length == 0) {
return 0;
}
if (arr[0] == n) {
return 1 + countOccurrences(arr, n - 1);
}
return countOccurrences(arr, n - 1);
}
}
If you can use only two parameters, then try:
public static int countOccurrences(int[] arr, int n) {
if (arr.length == 0) {
return 0;
}
if (arr[0] == n) {
return 1 + countOccurrences(Arrays.copyOfRange(arr, 1, arr.length), n);
}
return countOccurrences(Arrays.copyOfRange(arr, 1, arr.length), n);
}
the problem with above code is that the base condition will never be satisfied as you are never trying to reduce the length of the array. To keep track of length traversed, you can use a variable that starts from end to start ( or from start to end your choice ) . And let's say , num is the value that you want to count. Then you can change your code to like this :
public class CountFrequency {
public static void main(String[] args) {
int A[] = { 1, 2, 3, 4, 5, 5 };
int count = countOccurences(A, 5);
System.out.println(count);
}
private static int countOccurences(int[] arr, int num) {
return helper(arr, num, arr.length - 1);
}
private static int helper(int[] arr, int num, int i) {
if (i == -1) {
return 0;
}
if (arr[i] == num)
return 1 + helper(arr, num, i - 1);
else
return helper(arr, num, i - 1);
}
}
and the output is
2

How to find out the odd integers in an array using a recursive method?

I am trying to write a method that finds how many odd numbers are between first position and last position. The method accepts an array, and then two ints for the low and high position. This method needs to be made recursively. Here is what I have so far. Here is the method call and the int array. I'm getting an output of 1 but the answer should be 2.
int array [] = {5, 2, 5, 6, 3, 1};
int n = countOddsInRange(array, 1, 4)
public static int countOddsInRange(int [] a, int first, int last)
{
int count = 0;
if(first <= last)
{
countOddsInRange(a, a[first + 1], a[last]);
if(a[first] % 2 == 0)
{
count++;
}
}
return count;
}
You have some bugs in your code :
You are counting even numbers, not odd. Change your condition to if(a[first] % 2 != 0)
The recursive call should get indices of the array, not the values in those locations.
You should add the result of the recursive call to the total : count+=countOddsInRange(a, first + 1, last)
To summarize :
public static int countOddsInRange(int [] a, int first, int last)
{
int count = 0;
if(first <= last)
{
count+=countOddsInRange(a, first + 1, last);
if(a[first] % 2 != 0)
{
count++;
}
}
return count;
}
Your function should looks like :
public static int countOddNumber(int [] a, int first, int last){
return countOddNumber(a, first, last, 0);
}
public static int countOddNumber(int [] a, int first, int last, int count){
//in recursive function start with termination test.
if (first == last){
return count + isOdd(a[first]);
}
else{
return countOddNumber(a, first+1, last, count) + isOdd(a[first]);
}
}
public static int isOdd(int number){
if(number%2 == 0){return 1;}
else{return 0}
}
You should also add a test to check if first is lesser than last to avoid infinite loop ;)
PS : filter element whose mod(element,2) = 0 and then get the size of the collection. That method use functional style too, and use new Java8 feature. And is probably much more faster.
public class CountOddsInRange {
public static void main(String[] args) {
int array[] = {5, 2, 5, 6, 3, 1};
int n = countOddsInRange(array, 0, array.length - 1);
System.out.println("No of odds is " + n);
}
public static int countOddsInRange(int [] a, int first, int last)
{
int count = 0;
if(first <= last)
{
count+=countOddsInRange(a, first + 1, last);
if(a[first] % 2 != 0)
{
count++;
}
}
return count;
}
}
public class CountOddsInRange {
public static void main(String[] args) {
int array[] = {5, 2, 5, 6, 3, 1};
int n = countOddsInRange(array, 0, array.length - 1, 0);
System.out.println("No of odds is " + n);
}
public static int countOddsInRange(int[] a, int first, int last, int count) {
if (first <= last) {
if (a[first] % 2 != 0) {
count++;
}
return countOddsInRange(a, first + 1, last, count);
}
return count;
}
}

recursively sum the integers in an array

I have a program that I'm trying to make for class that returns the sum of all the integers in an array using recursion. Here is my program thus far:
public class SumOfArray {
private int[] a;
private int n;
private int result;
public int sumOfArray(int[] a) {
this.a = a;
n = a.length;
if (n == 0) // base case
result = 0;
else
result = a[n] + sumOfArray(a[n-1]);
return result;
} // End SumOfArray method
} // End SumOfArray Class
But I'm getting three error which are all related, I believe, but I can't figure out why it is finding a type of null:
SumOfArray.java:25: sumOfArray(int[]) in SumOfArray cannot be applied to (int)
result = a[n] + sumOfArray(a[n-1]);
^
SumOfArray.java:25: operator + cannot be applied to int,sumOfArray
result = a[n] + sumOfArray(a[n-1]);
^
SumOfArray.java:25: incompatible types
found : <nulltype>
required: int
result = a[n] + sumOfArray(a[n-1]);
^
3 errors
The solution is simpler than it looks, try this (assuming an array with non-zero length):
public int sumOfArray(int[] a, int n) {
if (n == 0)
return a[n];
else
return a[n] + sumOfArray(a, n-1);
}
Call it like this:
int[] a = { 1, 2, 3, 4, 5 };
int sum = sumOfArray(a, a.length-1);
The issue is that a[n-1] is an int, whereas sumOfArray expects an array of int.
Hint: you can simplify things by making sumOfArray take the array and the starting (or ending) index.
a[n-1]
is getting the int at n-1, not the array from 0 to n-1.
try using
Arrays.copyOf(a, a.length-1);
instead
How about this recursive solution? You make a smaller sub-array which contains elements from the second to the end. This recursion continues until the array size becomes 1.
import java.util.Arrays;
public class Sum {
public static void main(String[] args){
int[] arr = {1,2,3,4,5};
System.out.println(sum(arr)); // 15
}
public static int sum(int[] array){
if(array.length == 1){
return array[0];
}
int[] subArr = Arrays.copyOfRange(array, 1, array.length);
return array[0] + sum(subArr);
}
}
a is an int array. Thus a[n-1] is an int. You are passing an int to sumOfArray which expects an array and not an int.
Try this if you don't want to pass the length of the array :
private static int sumOfArray(int[] array) {
if (1 == array.length) {
return array[array.length - 1];
}
return array[0] + sumOfArray(Arrays.copyOfRange(array, 1, array.length));
}
Offcourse you need to check if the array is empty or not.
This is the one recursive solution with complexity O(N).and with input parameter A[] only.
You can handle null and empty(0 length) case specifically as Its returning 0 in this solution. You throw Exception as well in this case.
/*
* Complexity is O(N)
*/
public int recursiveSum2(int A[])
{
if(A == null || A.length==0)
{
return 0;
}
else
{
return recursiveSum2Internal(A,A.length-1);
}
}
private int recursiveSum2Internal(int A[],int length)
{
if(length ==0 )
{
return A[length];
}
else
{
return A[length]+recursiveSum2Internal(A, length-1);
}
}
without any predefined function.
public static int sum(int input[]) {
int n = input.length;
if (n == 0) // base case
return 0;
int small[]=new int[n-1];
for(int i=1;i<n;i++)
{
small[i-1]=input[i];
}
return input[0]+sum(small);
}
private static int sum(int[] arr) {
// TODO Auto-generated method stub
int n = arr.length;
if(n==1)
{
return arr[n-1];
}
int ans = arr[0]+sum(Arrays.copyOf(arr, n-1));
return ans;
}
Simplified version:
//acc -> result accumlator, len - current length of array
public static int sum(int[] arr, int len, int acc) {
return len == 0 ? acc : sum(arr, len-1, arr[len-1]+ acc);
}
public static void main(String[] args) {
int[] arr= { 5, 1, 6, 2};
System.out.println(sum(arr, arr.length, 0));
}

Finding Max value in an array using recursion

For one of the questions i was asked to solve, I found the max value of an array using a for loop, so i tried to find it using recursion and this is what I came up with:
public static int findMax(int[] a, int head, int last) {
int max = 0;
if (head == last) {
return a[head];
} else if (a[head] < a[last]) {
return findMax(a, head + 1, last);
} else {
return a[head];
}
}
So it works fine and gets the max value, but my question is : is it ok to have for the base case return a[head] and for the case when the value at the head is > the value at last?
You could just as easily do it with only one counter, just the index of the value you want to compare this time:
public static int findMax(int[] a, int index) {
if (index > 0) {
return Math.max(a[index], findMax(a, index-1))
} else {
return a[0];
}
}
This much better shows what is going on, and uses the default "recursion" layout, e.g. with a common base step. Initial call is by doing findMax(a, a.length-1).
It's actually much simpler than that. The base case is if you've reached the end of the array (the 'else' part of the ternary control block below). Otherwise you return the max of the current and the recursive call.
public static int findMax(int[] a) {
return findMax(a, 0);
}
private static int findMax(int[] a, int i) {
return i < a.length
? Math.max(a[i], findMax(a, i + 1))
: Integer.MIN_VALUE;
}
At each element, you return the larger of the current element, and all of the elements with a greater index. Integer.MIN_VALUE will be returned only on empty arrays. This runs in linear time.
I would solve this by dividing the array in to the half on each recursive call.
findMax(int[] data, int a, int b)
where a and b are array indices.
The stop condition is when b - a <= 1, then they are neighbours and the max is max(a,b);
The initial call:
findMax(int[] data, int 0, data.length -1);
This reduces the maximum recursion depth from N to log2(N).
But the search effort still stays O(N).
This would result in
int findMax(int[] data, int a, int b) {
if (b - a <= 1) {
return Math.max(data[a], data[b]);
} else {
int mid = (a+b) /2; // this can overflow for values near Integer.Max: can be solved by a + (b-a) / 2;
int leftMax = findMax(a, mid);
int rightMax = findMax(mid +1, b);
return Math.max(leftMax, rightMax);
}
}
I came across this thread and it helped me a lot. Attached is my complete code in both recursion and divide&conquer cases.
The run time for divide&conquer is slightly better than recursion.
//use divide and conquer.
public int findMaxDivideConquer(int[] arr){
return findMaxDivideConquerHelper(arr, 0, arr.length-1);
}
private int findMaxDivideConquerHelper(int[] arr, int start, int end){
//base case
if(end - start <= 1) return Math.max(arr[start], arr[end]);
//divide
int mid = start + ( end - start )/2;
int leftMax =findMaxDivideConquerHelper(arr, start, mid);
int rightMax =findMaxDivideConquerHelper(arr, mid+1, end);
//conquer
return Math.max( leftMax, rightMax );
}
// use recursion. return the max of the current and recursive call
public int findMaxRec(int[] arr){
return findMaxRec(arr, 0);
}
private int findMaxRec(int[] arr, int i){
if (i == arr.length) {
return Integer.MIN_VALUE;
}
return Math.max(arr[i], findMaxRec(arr, i+1));
}
What about this one ?
public static int maxElement(int[] a, int index, int max) {
int largest = max;
while (index < a.length-1) {
//If current is the first element then override largest
if (index == 0) {
largest = a[0];
}
if (largest < a[index+1]) {
largest = a[index+1];
System.out.println("New Largest : " + largest); //Just to track the change in largest value
}
maxElement(a,index+1,largest);
}
return largest;
}
I know its an old Thread, but maybe this helps!
public static int max(int[] a, int n) {
if(n < 0) {
return Integer.MIN_VALUE;
}
return Math.max(a[n-1], max(a, n - 2));
}
class Test
{
int high;
int arr[];
int n;
Test()
{
n=5;
arr = new int[n];
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
high = arr[0];
}
public static void main(String[] args)
{
Test t = new Test();
t.findHigh(0);
t.printHigh();
}
public void printHigh()
{
System.out.println("highest = "+high);
}
public void findHigh(int i)
{
if(i > n-1)
{
return;
}
if(arr[i] > high)
{
high = arr[i];
}
findHigh(i+1);
return;
}
}
You can do it recursively as follows.
Recurrent relation it something like this.
f(a,n) = a[n] if n == size
= f(a,n+1) if n != size
Implementation is as follows.
private static int getMaxRecursive(int[] arr,int pos) {
if(pos == (arr.length-1)) {
return arr[pos];
} else {
return Math.max(arr[pos], getMaxRecursive(arr, pos+1));
}
}
and call will look like this
int maxElement = getMaxRecursive(arr,0);
its not okay!
your code will not find the maximum element in the array, it will only return the element that has a higher value than the elements next to it, to solve this problem,the maximum value element in the range can be passed as argument for the recursive method.
private static int findMax(int[] a, int head, int last,int max) {
if(last == head) {
return max;
}
else if (a[head] > a[last]) {
max = a[head];
return findMax(a, head, last - 1, max);
} else {
max = a[last];
return findMax(a, head + 1, last, max);
}
}
Optimized solution
public class Test1 {
public static int findMax(int[] a, int head, int last) {
int max = 0, max1 = 0;
if (head == last) {
return a[head];
} else if (a[head] < a[last]) {
max = findMax(a, head + 1, last);
} else
max = findMax(a, head, last - 1);
if (max >= max1) {
max1 = max;
}
return max1;
}
public static void main(String[] args) {
int arr[] = {1001, 0, 2, 1002, 2500, 3, 1000, 7, 5, 100};
int i = findMax(arr, 0, 9);
System.out.println(i);
}
}
Thanks #Robert Columbia for the suggestion!
Update: This following function is going to recursively start from index 0 and it will keep adding to this index value till it's equal to the Length of the array, if it's more we should stop and return 0. Once we're doing that, we need to get the max of every two items in the array so, for example:
A = [1 , 2 , 3 ];
A[0] ( 1 ) vs A[1] ( 2 ) = 2
A[1] ( 2 ) vs A[2] ( 3 ) = 3
Max(2,3) = 3 ( The answer )
public int GetMax(int [] A, int index) {
index += 1;
if (index >= A.Length) return 0;
return Math.Max(A[index], GetMax(A, index + 1));
}
static int maximumOFArray(int[] array,int n) {
int max=Integer.MIN_VALUE;
if(n==1) return array[0];
else
max=maximumOFArray(array, --n);
max= max>array[n] ? max : array[n];
return max;
}
private static int getMax(int [] arr, int idx) {
if (idx==arr.length-1 ) return arr[idx];
return Math.max(arr[idx], getMax (arr,idx+1 ));
}
public class FindMaxArrayNumber {
public static int findByIteration(int[] array) {
int max = array[0];
for (int j : array) {
max = Math.max(j, max);
}
return max;
}
public static int findByRecursion(int[] array, int index) {
return index > 0
? Math.max(array[index], findByRecursion(array, index - 1))
: array[0];
}
public static void main(String[] args) {
int[] array = new int[]{1, 2, 12, 3, 4, 5, 6};
int maxNumberByIteration = findByIteration(array);
int maxNumberByRecursion = findByRecursion(array, array.length - 1);
System.out.println("maxNumberByIteration: " + maxNumberByIteration);
System.out.println("maxNumberByRecursion: " + maxNumberByRecursion);
// Outputs:
// maxNumberByIteration: 12
// maxNumberByRecursion: 12
}
}
int maximum = getMaxValue ( arr[arr.length - 1 ], arr, arr.length - 1 );
public static int getMaxValue ( int max, int arr[], int index )
{
if ( index < 0 )
return max;
if ( max < arr[index] )
max = arr[index];
return getMaxValue ( max, arr, index - 1 );
}
I felt that using a tracker for current maximum value would be good.

Java grouping algorithm

Given an array of ints, is it possible to choose a group of some of the ints, such that the group sums to the given target, with this additional constraint: if there are numbers in the array that are adjacent and the identical value, they must either all be chosen, or none of them chosen. For example, with the array {1, 2, 2, 2, 5, 2}, either all three 2's in the middle must be chosen or not, all as a group. (one loop can be used to find the extent of the identical values).
The test scenarios are below
groupSumClump(0, {2, 4, 8}, 10) → true true OK
groupSumClump(0, {1, 2, 4, 8, 1}, 14) → true true OK
groupSumClump(0, {2, 4, 4, 8}, 14) → false false OK
groupSumClump(0, {8, 2, 2, 1}, 9) → true false X --->Failing
groupSumClump(0, {8, 2, 2, 1}, 11) → false false OK
groupSumClump(0, {1}, 1) → true false X --->Failing
groupSumClump(0, {9}, 1) → false false OK
other tests OK
Snippet is as below
private int sum(final Integer start, final Collection<Integer> list) {
int sum = start;
for (final int i : list) {
sum += i;
}
return sum;
}
public boolean groupSumClump(final int start, final int[] nums, final int target) {
for (int i = 0; i < nums.length-1; i++) {
if(nums[i] == nums[i+1]){//group selected logic
int sum = nums[i] + nums[i+1];//is this Ok ?
nums[i] =sum;
nums[i+1]=0;
}else{
//how to handle the logic for group not selected.
}
}
final List<Integer> fixed = new ArrayList();
final List<Integer> candidates = new ArrayList();
// fills candidates and fixed
for (int i = 0; i < nums.length; i++) {
final int cand = nums[i];
if (cand == 1 && i > 0) {
final int prev = nums[i - 1];
}else if (cand < target) {
candidates.add(cand);
}
}
// compute the sum of fixed
final int sumFixed = sum(0, fixed);
// if the sum of fixed is equals to target we don't need to do
//anything because we already know we need to return true.
if (sumFixed == target) {
return true;
}
if (sumFixed <= target && !candidates.isEmpty()) {
final Set<Set<Integer>> powerSets = powerSet(new HashSet(candidates));
for (final Set<Integer> set : powerSets) {
if (sumFixed + sum(0, set) == target) {
return true;
}
}
}
return false;
}
public <T> Set<Set<T>> powerSet(Set<T> originalSet) {
Set<Set<T>> sets = new HashSet<Set<T>>();
if(originalSet.isEmpty()) {
sets.add(new HashSet<T>());
return sets;
}
List<T> list = new ArrayList<T>(originalSet);
T head = list.get(0);
Set<T> rest = new HashSet<T>(list.subList(1, list.size()));
for (Set<T> set : powerSet(rest)) {
Set<T> newSet = new HashSet<T>();
newSet.add(head);
newSet.addAll(set);
sets.add(newSet);
sets.add(set);
}
return sets;
}
could you let me whats the problem with the code and why is it failing for test scenarios as mentioned.
i want to know what is the logic for group not selected?
Here is the full solution which passes all your test cases.
Please edit yourself to make it fit to your APIs ^_^
public static void main(String[] args) {
int nums [] = new int[]{2, 4, 8};
int target = 10;
int nums_another [] = grouped (nums);
System.out.println(viable(0, nums_another, 0, target));
}
private static int [] grouped (int nums []) {
int nums_another[] = new int [nums.length];
int i = 0;
int j = 0;
i++;
int c = 1;
while (i < nums.length){
if (nums[i] == nums[i-1]) { // count identical numbers
c++;
}
else { // not identical, store sum of previous identical numbers (possibly only 1 number)
if (nums[i-1] != 0) {
nums_another[j] = nums[i-1] * c;
j++;
}
c = 1;
}
i++;
}
if (nums[i-1] != 0) { // store last
nums_another [j] = nums[i-1] * c;
}
return nums_another;
}
/* partial_sum + sub array of "array from start to 0's" -> target */
private static boolean viable (int partial_sum, int array[], int start, int target) {
if (partial_sum == target) {
return true;
}
else if (start >= array.length || array[start] == 0) {
return false;
}
else { // Key step
return viable (partial_sum + array[start], array, start + 1, target)
|| viable (partial_sum, array, start + 1, target);
}
}
Key step:
return whether target is viable through sub array, test both cases start is included or not.
One helpful first step would be to replace the array with a LinkedMultiSet. Not a standard runtime collection but easy enough to imagine, find an implementation, or make.

Categories

Resources