I have this assignment for school and it wants me to use recursion. I'm new to recursion and I understand it but I just can't figure out why this method isn't working the way it's suppose to. These are the instructions that were given to me and this is my code
// This method will be completed by the student!
// The student should implement the binary search algorithm using recursion. The
// method will originally be called by the GUI logic when the Search button is clicked.
public int binarySearch(Integer[] targetArray, int targetValue, int lowIndex, int highIndex){
if (lowIndex > highIndex)
return -1;
int midIndex = lowIndex + (highIndex - lowIndex)/2;
if (targetValue == targetArray[midIndex])
return midIndex;
if(targetArray[midIndex] > targetValue)
binarySearch(targetArray, targetValue, lowIndex, midIndex - 1);
else if(targetArray[midIndex] < targetValue)
binarySearch(targetArray, targetValue, midIndex + 1, highIndex);
return -1; // replace this with your recursive binary search code
}
The program will ask the user to enter in a target value. It will then search an array using recursion to tell if the target value is in the array. The array holds the numbers {1, 3, 5, 6, 8, 9, 10, 12, 14, 15}. When I search for the number 5 a message box pops up and says "Number 5 not found!" but when I set the target value to 8 it finds it in the array
I take it the comment stems from the review?
public int binarySearch(int[] targetArray, int targetValue,
int lowIndex, int highIndex) {
if (lowIndex > highIndex)
return -1;
int midIndex = lowIndex + (highIndex - lowIndex)/2;
if (targetValue == targetArray[midIndex])
return midIndex;
if (targetArray[midIndex] > targetValue)
return binarySearch(targetArray, targetValue, lowIndex, midIndex - 1);
else //if(targetArray[midIndex] < targetValue)
return binarySearch(targetArray, targetValue, midIndex + 1, highIndex);
}
The solution is to remove the last else-if.
Also you did not return the results of the recursively found index.
(An int[] parameter instead of Integer[] would be better.)
Also normally (99% of the) programmers use {} with if.
Well I have figured out the solution. The if-else statement was suppose to return the values at the end.
public int binarySearch(Integer[] targetArray, int targetValue, int lowIndex, int highIndex){
if (lowIndex > highIndex)
return -1;
int midIndex = lowIndex + (highIndex - lowIndex)/2;
if (targetValue == targetArray[midIndex])
return midIndex;
if(targetArray[midIndex] > targetValue)
return binarySearch(targetArray, targetValue, lowIndex, midIndex - 1);
else //if(targetArray[midIndex] < targetValue)
return binarySearch(targetArray, targetValue, midIndex + 1, highIndex);
//return -1; // replace this with your recursive binary search code
}
Related
I was given an assignment and we are only allowed to use recursive methods to solve different problems given to us.
I'm fairly new to programming and I'm having a hard time wrapping my head around it.
One of the objectives in the assignment is to calculate the max value of all possible paths in any given 2D integer array. Basically what this means is that when given a 2D int array, I need to use recursion to go through all different paths (abiding to the rules of only moving one element down or one element to the right at a time) in the array and return the value of the path with the highest sum value of elements in that path.
For example: (just a random example, could be any 2D int array with no particular order or size)
int[][] arr = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}};
the output should be: '48' (1 + 5 + 9 + 10 + 11 + 12)
This is what I have so far (but I have a feeling I'm way off):
public static int maxVal(int[][] arr) {
return maxVal(arr, 0, 0);
} // end of method
// Returns the value of the maximal path in the
// given 2D array, starting at location (i,j)
private static int maxVal(int[][] arr, int i, int j) {
// terminates when reaches last element
if ((i + 1) == arr.length && (j + 1) == arr[0].length) {
return 0;
} else {
// if the elemnt is at the last column
if ((i + 1) == arr.length) {
return maxVal(arr, i, j) + arr[i][j - 1];
// if element is at the last row
} else if ((j + 1) == arr[0].length) {
return maxVal(arr, i, j) + arr[i - 1][j];
} else {
return maxVal(arr, i, j) + arr[i - 1][j - 1];
}
}
}
I keep getting a StackOverFlowError. Any suggestions would be very helpful.
If you look closely, you will see that you are calling the same method over and over again return maxVal(arr, i, j), this will cause the SOF exception because there will be infi recursion calls since nothing is changing that will trigger the base cases.
You should instead return the current value added to the max value of the right/bottom.
private static int maxVal(int[][] arr, int i, int j)
{
if (i >= arr.length || i < 0 || j >= arr[i].length || j < 0) return 0;
int right = maxVal(arr, i, j + 1);
int bottom = maxVal(arr, i + 1, j);
return arr[i][j] + Math.max(right, bottom);
}
Try not to get lost in the recursion rabbit hole, instead set the correct base case which is once you reach an invalid i or j, you should just return 0 (end of current path)
if (i >= arr.length || i < 0 || j >= arr[i].length || j < 0) return 0;
if both indicies are valid, you will then have to recursively calculate the right and bottom values until it eventually reaches the end of the path (invalid indicies)
After that's done you will have two values, that are the result of the max sum of possible paths from your current right and current bottom, then you add your current value to the max value (right/bottom) and return it.
I am learning recursion so trying to practise it by implementing BinarySearch algorithm.
public class BinarySearch {
public int search(int[] items, int searchTerm, int startIndex, int endIndex) {
int midIndex = (startIndex + endIndex)/2 ;
System.out.println("Midpoint: "+midIndex);
if(searchTerm == items[midIndex]) {
return midIndex;
} else if(searchTerm > items[midIndex]) {
search(items, searchTerm, midIndex, endIndex);
} else if(searchTerm < items[midIndex]) {
search(items, searchTerm, startIndex, midIndex);
} else {
return -1;
}
return -1;
}
public static void main(String[] args) {
BinarySearch bs = new BinarySearch();
int[] items = { 1, 7, 9, 11, 22, 55, 67 };
int index = bs.search(items, 7, 0, items.length-1);
System.out.println(index);
}
}
search is the method that is called recursively with array of items, the value that I want to search and start & end index of the array where item could potentially be there.
First, I get the midpoint and if the item at midpoint matches the searchTerm then I return it. If searchTerm is greater than value at midpoint then I call the search method again with midpoint as startIndex and last item in the array as endIndex.
Similarly, if searchTerm is less than value at midpoint, then pass startIndex and midpoint as start and end value to search in.
Lets say, I want to search for 7. In the first iteration, 3 would be the midpoint so value at index 3 would be 11. Since, 7 < 11, search will be called again with startIndex as 0 and endIndex as 3. Now, midpoint would be 7, so the index of 7 (which is 1) should be returned. However, the value returned is -1 which is not correct.
When I tried troubleshooting it using Eclipse debugger, I found that even after the match is found at
if(searchTerm == items[midIndex]) {
return midIndex;
}
instead of exiting the method, the below code gets executed
else if(searchTerm < items[midIndex]) {
search(items, searchTerm, startIndex, midIndex);
}
And then it returns -1. I feel it could be something to do with recursion as the previous invocation of search() would still be in the stack due to recursive nature of the code and it might be popping out of the stack. However, I can't really understand it. What would be the correct way to implement BinarySearch using recursion?
public int search(int[] items, int searchTerm, int startIndex, int endIndex)
{
int midIndex = (startIndex + endIndex) / 2;
if (startIndex > endIndex)
return -1;
else if (searchTerm == items[midIndex])
return midIndex;
else if (searchTerm < items[midIndex])
return search(items, searchTerm, startIndex, midIndex - 1);
else // (searchTerm > items[midIndex])
return search(items, searchTerm, midIndex + 1, endIndex);
}
In this version of the binary search I used midIndex ± 1: I did this because in your if statement you already check if items[midIndex] is equal or not to searchTerm, that's why considering items[midIndex] in the next calls is unnecessary.
You are not returning your recursive calls.
public int search(int[] items, int searchTerm, int startIndex, int endIndex) {
int midIndex = (startIndex + endIndex)/2 ;
System.out.println("Midpoint: "+midIndex);
if(searchTerm == items[midIndex]) {
return midIndex;
} else if(searchTerm > items[midIndex]) {
return search(items, searchTerm, midIndex, endIndex);
} else if(searchTerm < items[midIndex]) {
return search(items, searchTerm, startIndex, midIndex);
} else {
return -1;
}
return -1;
}
UPDATE
Recursion works with a Method Stack as you may know. So when you don't return the value back when you find the element, Your final recursion call will always return -1 as it is the last line in the method.
That is why you got -1.
I need to write a recursive method to count the number of odd integers in an array.
Here's my code so far:
public static int countOdd(int[] numbers, int startIndex, int endIndex) {
if (startIndex == endIndex) {
if (numbers[startIndex] % 2 != 0) {
return 1;
} else {
return 0;
}
} else {
return countOdd(numbers, startIndex, endIndex - 1);
}
}
Your recursive line is incorrect:
return countOdd(numbers, startIndex, endIndex - 1);
You've lost whether the endIndex is odd. This would help:
return countOdd(numbers, startIndex, endIndex - 1) +
countOdd(numbers, endIndex, endIndex);
And I'm not sure if you're calling it right, I'm assuming it would be:
countOdd(numbers, 0, numbers.length-1);
Explainer: In order to understand how to implement it, you need to break the problem down. If I want to recursively count the odd numbers in an array:
[a, b, c, d, e, f, g, .... z]
The code above basically does this:
countOdd([a, b, c, d, e, f, g, ...y]) + countOdd([z])
Notice second operand will return 0 or 1 because the subset is of size 1. The first operand basically is length 1 smaller. Recursion continues:
countOdd([a, b, c, d.... x]) + countOdd([y]) + countOdd([z])
...
countOdd([a]) + countOdd([b]) + countOdd([c]) + ... countOdd([z])
And once they are all size 1 subsets, it can calculate it.
0 + 1 + 0 + 1 + 1 ..
And return the result from summing individual counts of odd digits.
Extra Notes: Notice that the recursion could be done differently, but still come up with the same result (eg.:
return countOdd(numbers, startIndex, startIndex) +
countOdd(numbers, startIndex + 1, endIndex);
Can you please try:
<your main class>{
//global variables
int index = 0;
int[] array = {1,2,3,4,5};
int counter = 0;
int totalOfOddNumbers = countOddIntegers(index);
System.out.println(totalOfOddNumbers);
}
private int countOddIntegers(int i){
if (array[i] == 1) || (array[i]%2 != 0) counter ++;
if (i != array.length - 1) return countOddIntegers(i+1);
else return counter;
}
Is it possible to count the number of comparisons made by a recursive binary search? If so, how?
Here is the search I am referring to:
//binary search
public static int binarySearch(int[] items, int start, int end, int goal)
{
if (start > end)
return (-1);
else
{
int mid = (start + end)/2;
if (goal == items[mid])
return (mid);
else
if (goal < items[mid])
return (binarySearch(items, start, mid - 1, goal));
else
return (binarySearch(items, mid + 1, end, goal));
}
}//end binarySearch
Declare your count variable outside of the method. Then add 1 each time that you call the method.
long count = 0;
//binary search
public static int binarySearch(int[] items, int start, int end, int goal)
{
count += 1
if (start > end)
return (-1);
else
{
int mid = (start + end)/2;
if (goal == items[mid])
return (mid);
else
if (goal < items[mid])
return (binarySearch(items, start, mid - 1, goal));
else
return (binarySearch(items, mid + 1, end, goal));
}
}//end binarySearch
Your most likely approach if you want to caller to be able to access the count is to pass in an accumulator into your binary search. In java 7 or less, AtomicLong may be a good choice (though it does have some overhead). In java 8, a LongAdder would also be good:
public static int binarySearch(int[] items, int start, int end, int goal, AtomicLong counter) {
}
and each time you do a comparison, you would just increment the count:
counter.incrementAndGet()
When you exit the search, the counter will contain the number of comparisons:
long count = counter.get()
Here is my code:
public int sum(int[] array, int index)
{
//int index is the number of elements in the array.
//Here is my base case:
if (index == 0)
return 0;
//Now it's time for the recursion
else
return array[index] + sum(array, index + 1);
}
I keep on getting an out of bounds error, but I don't what I am doing wrong.
Your base condition is faulty. It should be:
if (index == array.length)
Note, you need to pass index = 0 on first call. If you are passing index = array.length - 1, then keep the base case as it is, and change the recursive method invocation to pass index - 1, instead of index + 1.
However, do you really need recursion? I would seriously give it hundreds of thoughts before reaching out for recursion instead of loop for this task.
Try,
public static void main(String[] args){
int arr[] = {3, 4, 6, 7};
System.out.println(sum(arr, arr.length-1));
}
public static int sum(int[] array, int index) {
if (index == 0) {
return array[0];
} else {
return array[index] + sum(array, index - 1);
}
}
instead of going from 0 to highest index , go from highest index to 0, i did (index -1) because you said index is total elements, so if array has 10 elements, last element has index 9
public int sum(int[] array, int index)
{
//int index is the number of elements in the array.
//Here is my base case:
if (index == 0)
return 0;
//Now it's time for the recursion
else
return array[index-1] + sum(array, (index - 1);
}
# Masud - you're code has a logical error though (i'm beginner Java so sorry if i'm incorrect).
return array[index] + sum(array, index - 1);
array[index]
will receive a out-of-bounds error as index starts at 0 - hence meaning there won't be an index there.
'index - 1' would work.
Also, this would change your base case to return '0' as returning array[0] will have array[0] added twice and an incorrect sum.
This is my code:
public static int sumArrayRecursion(int array[], int n){
if (n == 0){
return 0;
}
else {
return array[n-1] + sumArrayRecursion(array, n-1);
}
}
If you are using Java 1.8 you can do the following
public int sum(int[] array)
{
return (int)array.stream().sum();
}
or even
public int sum(int[] array)
{
return (int)array.sum();
}