don't know how to prevent java.lang.StackOverflowError - java

I am supposed to write a recursive(!) method to count the amount of occurrences of a given integer in an integer array and return true if even and false if odd. This is my code so far:
public static boolean evenNumberOf(int x, int[] arr) {
if (arr == null || arr.length == 0)
return false;
int count = counting(x, arr, 0, 0);
if (count % 2 == 0) {
System.out.print("true");
return true;
} else {
System.out.print("false");
return false;
}
}
public static int counting(int x, int[] arr, int index, int count) {
if (arr[index] == x && index < arr.length) {
return counting(x, arr, index++, count++);
} else {
return counting(x, arr, index++, count);
}
}
It works for
evenNumberOf(2, new int[] { 1, 2, 3, 2 });
but it gives java.lang.StackOverflowError for
evenNumberOf(1, new int[] { 1, 2, 3, 2 });
I am not sure how to prevent this endless recursive loop, as I'm new to programming and it's my first time using recursion.
Thanks in advance.

Any recursion should have a stop condition and 1 or more recursive calls.
in this example, the stop condition is index >= arr.length so you start writing the function as folows:
public static int counting(int x, int[] arr, int index) {
if (index >= arr.length) {
return 0;//there are 0 x's between index and arr.length
}
after you handled the stop condition, you need to write the rest:
public static int counting(int x, int[] arr, int index) {
if (index >= arr.length) {
return 0;//there are 0 x's between index and arr.length
}
int countAfterIndex = counting(x, arr, index+1);//the amount of x's starting from index+1
if (x == arr[index]) {
return countAfterIndex + 1;//there is 1 more to add
} else {
return countAfterIndex; //the amount of x's after index is the same as the amount from index.
}
}

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

LeetCode Dynamic Programming Robber Question Mistake

I am currently doing LeetCode's Robber Question. I passed 68/69 test cases, and the only one I failed is the following: an array full or zeros like this [0, 0, 0, 0, 0.....]. Can you please explain to me how to fix my code to fix this error? Also, if you have any suggestions about optimization, please let me know! My code:
class Solution {
public int rob(int[] nums) {
if (nums.length == 0 ) {
return 0;
}
if (nums.length == 1) {
return nums[0];
}
int[] memo = new int[nums.length];
return Math.max(dp(0, nums, memo), dp(1, nums, memo));
}
public int dp(int index, int[] nums, int[] memo) {
int max;
if (memo[index] != 0) {
return memo[index];
}
if (index == nums.length - 1 || index == nums.length - 2) {
max = nums[index];
} else if (index == nums.length - 3) {
max = nums[index] + nums[nums.length - 1];
}
else {
max = Math.max(nums[index] + dp(index + 2, nums, memo), nums[index] + dp(index + 3, nums, memo));
}
memo[index] = max;
return max;
}
}
This is how I have solved the same problem using bottom up DP which handles every test cases.
class Solution {
public int rob(int[] nums) {
int n=nums.length;
if(n==0)
return 0;
if(n==1)
return nums[0];
int[] dp= new int[n];
dp[0]=nums[0];
dp[1]=Math.max(nums[0],nums[1]);
for(int i=2;i<n;i++)
dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i]);
return dp[n-1];
}
The reason your code is failing for [0,0,0,0....] is because the answer is zero and your recursion base case if(memo[index] != 0) is never getting satisfied and resulting in StackOverflow . Below is the correct version of your code
class Solution {
public int rob(int[] nums) {
if (nums.length == 0 ) {
return 0;
}
if (nums.length == 1) {
return nums[0];
}
int[] memo = new int[nums.length];
Arrays.fill(memo,Integer.MAX_VALUE); // add this to check if memo is not updated
return Math.max(dp(0, nums, memo), dp(1, nums, memo));
}
public int dp(int index, int[] nums, int[] memo) {
int max;
if (memo[index] != Integer.MAX_VALUE) { // check for this condition
return memo[index];
}
if (index == nums.length - 1 || index == nums.length - 2) {
max = nums[index];
} else if (index == nums.length - 3) {
max = nums[index] + nums[nums.length - 1];
}
else {
max = Math.max(nums[index] + dp(index + 2, nums, memo), nums[index] + dp(index + 3, nums, memo));
}
memo[index] = max;
return max;
}
}

Java Recursive function that determines if there are two consecutive numbers which are equal

I am quite confused about how to write this code recursively. I must create a method that determines if there are two consecutive numbers which are equal within a specific range on an array.
An example of an array that should return true would be: 3, 2, 2, 1
Where i=0 and j=3.
So far this is my code, but it does not implement the problem correctly.
private static boolean problem1(int[] arr, int i, int j)
{
int[] newArray = Arrays.copyOfRange(arr, i, j+1); //Create a new array that only contains the specific given range
for(int x = i; x < newArray.length; x++){
int y = (x+1);
if(newArray[x]==newArray[y]){
return true;
}
}
return false;
}
private static boolean problem1(int[] A, int i, int j) {
if (A == null || A.length == 1 || A.length == 0 || i == j) {
return false;
}
if (A[i] == A[i + 1]) {
return true;
}
i++;
return problem1(A, i, j);
}
private static boolean problem1(int[] arr, int i, int j) {
if (arr == null || arr.length == 1 || arr.length == 0 || i == j) {
return false;
}
if (arr[i] == arr[j])
return true;
i++;
return problem1(arr, i, j);
}
Find the recursive function explanation in the code itself
import java.util.Arrays;
import java.util.Random;
public class RecurseFunc {
public static void main(String[] args) {
// int[] arr = new int[]{3,2,2,1};
int[] arr = new int[]{3,2,4,1,1};
// System.out.println(problem1(arr,0,3));
// System.out.println(problemRec(arr, 4,-1,0));
System.out.println(problemRecWrapper(new int[]{-1,2,4,1,0}, 4, 0));
}
static boolean problemRecWrapper(int[] arr, int arrLastIndex, int currentIndex) {
return problemRec(new int[]{-1,2,4,1,0}, 4, -1, 0);
}
/**
*
* #param arr Complete array
* #param arrLastIndex - Starting index point
* #param lastIndex - Last element index
* #param currentIndex - Current arr index
* #return
*/
static boolean problemRec(int[] arr, int arrLastIndex, int lastIndex, int currentIndex) {
if(currentIndex > arrLastIndex) {
return false;
}
if(lastIndex > 0 && arr[lastIndex] == arr[currentIndex]) {
return true;
}
currentIndex++;
return problemRec(arr, arrLastIndex,lastIndex,currentIndex);
}
}

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;
}
}

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.

Categories

Resources