LeetCode Dynamic Programming Robber Question Mistake - java

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

Related

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

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

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

Solving codingBat 'evenOdd' with one loop in Java

The question is about Solving this problem from codingBat in Java.
Problem Statement:
Return an array that contains the exact same numbers as the given array, but rearranged so that all the even numbers come before all the odd numbers. Other than that, the numbers can be in any order. You may modify and return the given array, or make a new array.
evenOdd({1, 0, 1, 0, 0, 1, 1}) → {0, 0, 0, 1, 1, 1, 1}
evenOdd({3, 3, 2}) → {2, 3, 3}
evenOdd({2, 2, 2}) → {2, 2, 2}
The Problem is simple with 2 loops I attempted at solving it with 1 it got too lengthy I believe, is there any other efficient way to solve the above problem using 1 loop?
do not use collections!
My solution:
public int[] evenOdd(int[] nums) {
boolean oddFound=false;
int count=-1;
int oddGap=0;
for(int i=0;i<nums.length;i++)
{
if(!(oddFound)&(nums[i]%2==0))
continue;
if((!oddFound)&(nums[i]%2==1))
{
oddFound=true;
count=i;
continue;
}
if((oddFound)&(nums[i]%2==1))
{
oddGap++;
continue;
}
if((oddFound)&(nums[i]%2==0))
{
int temp=nums[count];
nums[count]=nums[i];
nums[i]=temp;
if(i>0)
i--;
if(oddGap>0)
{
oddGap--;
count+=1;
oddFound=true;
continue;
}
oddFound=false;
}
}
return nums;
}
Since creating a new array is allowed, and the order of the numbers is irrelevant, I would use the following approach:
public int[] evenOdd(int[] nums) {
int[] output = new int[nums.length];
int evenPos = 0;
int oddPos = nums.length-1;
for (int i : nums) {
if (i%2==0) {
output[evenPos++]=i;
} else {
output[oddPos--]=i;
}
}
return output;
}
Update: A somewhat less readable version that doesn't require an extra array (along the lines of what #Seelenvirtuose suggests, just without the extra loops)
public int[] evenOdd(int[] nums) {
int evenPos = 0;
int oddPos = nums.length-1;
while (true) {
if (evenPos>=oddPos || evenPos>=nums.length || oddPos<0) {
break;
}
if (nums[evenPos]%2==0) {
evenPos++;
}
if (nums[oddPos]%2!=0) {
oddPos--;
}
if (evenPos<oddPos && nums[evenPos]%2 != 0 && nums[oddPos]%2 == 0) {
int tmp = nums[evenPos];
nums[evenPos] = nums[oddPos];
nums[oddPos] = tmp;
oddPos--;
evenPos++;
}
}
return nums;
}
You do not need any temporary lists or array because you can reorder the elements in-situ.
This is a simple algorithm:
Define two pointers, left and right (initially set to the bounds of the array).
As long as left does not exceed right and nums[left] is even, increment left.
As long as right does not exceed left and nums[right] is odd, decrement right.
If left is still less than right, swap the elements at positions left and right.
Repeat 2,3,4 as long as left is still less than right.
Got it? Here some code:
public int[] evenOdd(int[] nums) {
// (1)
int left = 0;
int right = nums.length -1;
do {
// (2)
while (left < right && nums[left] % 2 == 0)
left += 1;
// (3)
while (right > left && nums[right] % 2 != 0)
right -= 1;
// (4)
if (left < right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
} while (left < right); // (5)
return nums;
}
Okay! I finally jumped across this question which is actually closed but the solution by asker was almost there apart from failing in 2 cases which I fixed:
I commented out he code by asker which was making it fail in a couple of cases as seen in the question.
I think below is the simplest and most optimized solution:
public int[] evenOdd(int[] nums) {
int y=nums.length,x,a=0;
int temp=0;
for(x=0;x<y;x++)
{
if(nums[x]%2==0) {
if(a>(y-2))
return nums;
else{
//nums[a]=nums[a]+nums[x];
//nums[x]=nums[a]-nums[x];
//nums[a]=nums[a]-nums[x];
temp=nums[a];
nums[a]=nums[x];
nums[x]=temp;
a+=1;
}
}
return nums;
}
Traverse evenOdd from 0 to N.
for every even number encountered, copy it to the required position on the evenOdd array.
for every odd num encountered, store it in a separate array called oddnum.
After traversing the whole array, just copy the elements from oddnum to the Back of evenOdd.
Ex: evenOdd = {5,2,1,4}
Step 1. copy 5 to oddnum[0]
2. copy 2 to evenodd[0]
3. copy 1 to oddnum[1]
4. copy 1 to evenodd[1]
5. cpy oddnum[0] to evenOdd[2] and oddnum[1] to evenOdd[3]
Keeping to your restrictions, here's a one-loop answer:
public int[] evenOdd(int[] nums) {
int[] result = new int[nums.length];
int nextEven = 0;
int nextOdd = nums.length - 1;
for ( int num : nums )
{
if ( num % 2 == 0 )
result[ nextEven++ ] = num;
else
result[ nextOdd-- ] = num;
}
return result;
}
public int[] evenOdd(int[] nums) {
int count = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] % 2 == 0) {
int temp = nums[i];
nums[i] = nums[count];
nums[count] = temp;
count++;
}
}
return nums;
}
public int[] evenOdd(int[] nums) {
Stack stack = new Stack();
int[] nums2 = new int[nums.length];
for(int i = 0; i < nums.length; i++) {
if(nums[i] % 2 != 0) {
stack.push(nums[i]);
}
}
for(int i = 0; i < nums.length; i++) {
if(nums[i] % 2 == 0) {
stack.push(nums[i]);
}
}
for(int i = 0; i < nums.length; i++) {
nums2[i] = (Integer) stack.pop();
}
return nums2;
}
In-place version (stable):
We continually search for te first and last invalid values (first odd, before last even) and keep swapping them until they cross:
public int[] evenOdd(int[] nums) {
int first = 0, last = nums.length - 1;
while (first < last) {
while ((first < last) && isOdd(nums[last])) last--;
while ((first < last) && !isOdd(nums[first])) first++;
swap(nums, first, last);
}
return nums;
}
boolean isOdd(int num) { return (num & 1) == 1; }
void swap(int[] nums, int i, int j) {
int copy = nums[i];
nums[i] = nums[j];
nums[j] = copy;
}
With auxiliaries (stable):
We partition the even and odd values in separate lists and concatenate them back:
public int[] evenOdd(int[] nums) {
List<Integer> evens = new ArrayList<Integer>(nums.length);
List<Integer> odds = new ArrayList<Integer>(nums.length);
for (int num : nums)
if (isOdd(num)) odds.add(num);
else evens.add(num);
int[] results = new int[nums.length];
int i = 0;
for (int num : evens) results[i++] = num;
for (int num : odds) results[i++] = num;
return results;
}
boolean isOdd(int num) { return (num & 1) == 1; }
Simplified solution which uses Srteam API:
public int[] evenOdd(int[] nums) {
int[] evenOddArr = new int[nums.length];;
int[] evenArr = Arrays.stream(nums).filter(x -> x % 2 == 0).toArray();;
int[] oddArr = Arrays.stream(nums).filter(x -> x % 2 != 0).toArray();
evenOddArr = java.util.stream.IntStream.concat(Arrays.stream(evenArr), Arrays.stream(oddArr))
.toArray();
return evenOddArr;
}
It passes all the tests on CodingBat:

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.

How to use recursion in creating a binary search algorithm

I have been using my time off university to practice Java through coding algorithms. One of the algorithms I coded was the binary search:
public class BinarySearch {
private static int list[] = {3, 6, 7, 8, 9, 10};
public static void main(String[] args) {
BinarySearch b = new BinarySearch();
b.binarySearch(list);
}
public void binarySearch(int[] args) {
System.out.println("Binary search.");
int upperBound = args.length;
int lowerBound = 1;
int midpoint = (upperBound + lowerBound) / 2;
int difference = upperBound - lowerBound;
int search = 7;
for (int i = 0; i < args.length; i++) {
if (search < args[midpoint - 1] && difference != 1) {
upperBound = midpoint - 1;
midpoint = upperBound / 2;
} else if (search > args[midpoint - 1] && difference != 1) {
lowerBound = midpoint + 1;
midpoint = (lowerBound + upperBound) / 2;
} else if (search == args[midpoint - 1]) {
midpoint = midpoint - 1;
System.out.println("We found " + search + " at position " + midpoint + " in the list.");
i = args.length;
} else {
System.out.println("We couldn't find " + search + " in the list.");
i = args.length;
}
}
}
}
I really want to be able to write a much cleaner and efficient binary search algorithm, an alternative to what I've coded. I have seen examples of how recursion is used such as when doing factorial with numbers which I understand. However when coding something of this complexity I am confused on how to use it to my advantage. Therefore my question is how do I apply recursion when coding a binary search algorithm. And if you have any tips for me to perfect my recursion skills even if it has to be something that doesn't regard to binary search then please feel free to post.
If you really want to use recursion, this should do it.
public static int binarySearch(int[] a, int target) {
return binarySearch(a, 0, a.length-1, target);
}
public static int binarySearch(int[] a, int start, int end, int target) {
int middle = (start + end) / 2;
if(end < start) {
return -1;
}
if(target==a[middle]) {
return middle;
} else if(target<a[middle]) {
return binarySearch(a, start, middle - 1, target);
} else {
return binarySearch(a, middle + 1, end, target);
}
}
Here is an easier way of doing binary search:
public static int binarySearch(int intToSearch, int[] sortedArray) {
int lower = 0;
int upper = sortedArray.length - 1;
while (lower <= upper) {
int mid = lower + (upper - lower) / 2;
if(intToSearch < sortedArray[mid])
upper = mid - 1;
else if (intToSearch > sortedArray[mid])
lower = mid + 1;
else
return mid;
}
return -1; // Returns -1 if no match is found
}
Following is a code sample extracted from here.
public class BinarySearch {
public boolean find(int[] sortedValues, int value) {
return search(sortedValues, value, 0, sortedValues.length - 1);
}
private boolean search(int[] sorted, int value, int leftIndex, int rightIndex) {
// 1. index check
if (leftIndex > rightIndex) {
return false;
}
// 2. middle index
int middle = (rightIndex + leftIndex) / 2;
// 3. recursive invoke
if (sorted[middle] > value) {
return search(sorted, value, leftIndex, middle - 1);
} else if (sorted[middle] < value) {
return search(sorted, value, middle + 1, rightIndex);
} else {
return true;
}
}
}
You can find implementations of the below test cases against the above binary search implementation as well in the reference link.
1. shouldReturnFalseIfArrayIsEmpty()
2. shouldReturnFalseIfNotFoundInSortedOddArray()
3. shouldReturnFalseIfNotFoundInSortedEvenArray()
4. shouldReturnTrueIfFoundAsFirstInSortedArray()
5. shouldReturnTrueIfFoundAtEndInSortedArray()
6. shouldReturnTrueIfFoundInMiddleInSortedArray()
7. shouldReturnTrueIfFoundAnywhereInSortedArray()
8. shouldReturnFalseIfNotFoundInSortedArray()
A possible example is :
// need extra "helper" method, feed in params
public int binarySearch(int[] a, int x) {
return binarySearch(a, x, 0, a.length - 1);
}
// need extra low and high parameters
private int binarySearch(int[ ] a, int x,
int low, int high) {
if (low > high) return -1;
int mid = (low + high)/2;
if (a[mid] == x) return mid;
else if (a[mid] < x)
return binarySearch(a, x, mid+1, high);
else // last possibility: a[mid] > x
return binarySearch(a, x, low, mid-1);
}
Here you can check in C Binary Search, With and Without Recursion
Source : http://www.cs.utsa.edu/~wagner/CS3343/recursion/binsearch.html
Here is a algorithm which should get you going. Let your method signature be:
public boolean binarysearchRecursion(Array, begin_index,end_index, search_element)
Check if your begin_index > end_index if YES then return false.
Calculate mid_element for your input array.
Check if your search_element is equal to this mid_element. if YES return true
If mid_element > search_element Call your method with for range 0 - mid
If mid_element < search_element Call your method with for range mid+1 - Length_of_Array
Also as #DwB said in his comment you are better using loop to get things done. Some problems are recursive in nature(Like binary tree problems). But this one is not one of them.
This is another way of doing recursion:
int[] n = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
#Test
public void testRecursiveSolution() {
Assert.assertEquals(0, recursiveBinarySearch(1,n));
Assert.assertEquals(15, recursiveBinarySearch(16,n));
Assert.assertEquals(14, recursiveBinarySearch(15,n));
Assert.assertEquals(13, recursiveBinarySearch(14,n));
Assert.assertEquals(12, recursiveBinarySearch(13,n));
Assert.assertEquals(11, recursiveBinarySearch(12,n));
Assert.assertEquals(10, recursiveBinarySearch(11,n));
Assert.assertEquals(9, recursiveBinarySearch(10,n));
Assert.assertEquals(-1, recursiveBinarySearch(100,n));
}
private int recursiveBinarySearch(int n, int[] array) {
if(array.length==1) {
if(array[0]==n) {
return 0;
} else {
return -1;
}
} else {
int mid = (array.length-1)/2;
if(array[mid]==n) {
return mid;
} else if(array[mid]>n) {
return recursiveBinarySearch(n, Arrays.copyOfRange(array, 0, mid));
} else {
int returnIndex = recursiveBinarySearch(n, Arrays.copyOfRange(array, mid+1, array.length));
if(returnIndex>=0) {
return returnIndex+mid+1;
} else {
return returnIndex;
}
}
}
}
While it doesn't return the index, this at least returns the idea of 'yes' or 'no' that something is in the collection:
public static boolean recursive(int[] input, int valueToFind) {
if (input.length == 0) {
return false;
}
int mid = input.length / 2;
if (input[mid] == valueToFind) {
return true;
} else if (input[mid] > valueToFind) {
int[] smallerInput = Arrays.copyOfRange(input, 0, mid);
return recursive(smallerInput, valueToFind);
} else if (input[mid] < valueToFind) {
int[] smallerInput = Arrays.copyOfRange(input, mid+1, input.length);
return recursive(smallerInput, valueToFind);
}
return false;
}
A recursion BinarySearch with break conditions in case you can not find the value you are looking for
public interface Searcher{
public int search(int [] data, int target, int low, int high);
}
The Implementation
public class BinarySearch implements Searcher {
public int search(int[] data, int target, int low, int high) {
//The return variable
int retorno = -1;
if(low > high) return retorno;
int middle = (high + low)/2;
if(target == data[middle]){
retorno = data[middle];
}else if(target < data[middle] && (middle - 1 != high)){
//the (middle - 1 != high) avoids beeing locked inside a never ending recursion loop
retorno = search(data, target, low, middle - 1);
}else if(target > data[middle] && (middle - 1 != low)){
//the (middle - 1 != low) avoids beeing locked inside a never ending recursion loop
retorno = search(data, target, middle - 1, high);
}else if(middle - 1 == low || middle - 1 == high){
//Break condition if you can not find the desired balue
retorno = -1;
}
return retorno;
}
}

Categories

Resources