I try to use "randomized pivot" method to find the Kth min elem among given array.
[The code]
public class FindKthMin {
// Find the Kth min elem by randomized pivot.
private static void exchange (int[] givenArray, int firstIndex, int secondIndex) {
int tempElem = givenArray[firstIndex];
givenArray[firstIndex] = givenArray[secondIndex];
givenArray[secondIndex] = tempElem;
}
private static int partition (int[] givenArray, int start, int end, int pivotIndex) {
// Debug:
//System.out.println("debug: start = " + start);
//System.out.println(">> end = " + end);
//System.out.println(">> pivotIndex = " + pivotIndex);
int pivot = givenArray[pivotIndex];
int left = start - 1;
int right = end;
boolean hasDone = false;
while (!hasDone) {
while (!hasDone) {
left ++;
if (left == right) {
hasDone = true;
break;
}
if (givenArray[left] >= pivot) {
// Exchange givenArray[left] and the givenArray[right].
exchange(givenArray, left, right);
break;
}
}
while (!hasDone) {
right --;
if (left == right) {
hasDone = true;
break;
}
if (givenArray[right] < pivot) {
// Exchange the givenArray[right] and the givenArray[left].
exchange(givenArray, right, left);
break;
}
}
}
givenArray[right] = pivot;
// Debug:
//System.out.println(">> split = " + right);
//System.out.println();
return right;
}
private static int findKthMin_RanP_Helper (int[] givenArray, int start, int end, int k) {
if (start > end) return -1;
// Generate a random num in the range[start, end].
int rand = (int)(start + Math.random() * (end - start + 1));
// Using this random num as the pivot index to partition the array in the current scope.
int split = partition(givenArray, start, end, rand);
if (k == split + 1) return givenArray[split];
else if (k < split + 1) return findKthMin_RanP_Helper(givenArray, start, split - 1, k);
else return findKthMin_RanP_Helper(givenArray, split + 1, end, k);
}
public static int findKthMin_RanP (int[] givenArray, int k) {
int size = givenArray.length;
if (k < 1 || k > size) return -1;
return findKthMin_RanP_Helper(givenArray, 0, size - 1, k);
}
// Main method to test.
public static void main (String[] args) {
// Test data: {8, 9, 5, 2, 8, 4}.
int[] givenArray = {8, 9, 5, 2, 8, 4};
// Test finding the Kth min elem by randomized pivot method.
System.out.println("Test finding the Kth min elem by randomized pivot method, rest = " + findKthMin_RanP(givenArray, 1));
}
}
But the result is unstable, sometimes right and sometimes wrong.
Please have a look at the 5th row of findKthMin_RanP_Helper method:
If I change this int split = partition(givenArray, start, end, rand); to int split = partition(givenArray, start, end, end);, the result is always correct. I really can not find what's wrong with this.
EDIT:
The problem comes from the "partition", the new partition should like this:
private static int partition_second_version (int[] givenArray, int start, int end, int pivotIndex) {
int pivot = givenArray[pivotIndex];
int left = start;
int right = end;
while (left <= right) {
while (givenArray[left] < pivot) left ++;
while (givenArray[right] > pivot) right --;
if (left <= right) {
// Exchange givenArray[left] and givenArray[right].
exchange(givenArray, left, right);
left ++;
right --;
}
}
return left;
}
And the findKthMin_RanP_Helper should be changed like this:
private static int findKthMin_RanP_Helper (int[] givenArray, int start, int end, int k) {
if (start > end) return -1;
// Generate a random num in the range[start, end].
int rand = start + (int)(Math.random() * ((end - start) + 1));
// Using this random num as the pivot index to partition the array in the current scope.
int split = partition_second_version (givenArray, start, end, rand);
if (k == split) return givenArray[split - 1];
else if (k < split) return findKthMin_RanP_Helper(givenArray, start, split - 1, k);
else return findKthMin_RanP_Helper(givenArray, split, end, k);
}
Your partition routine could be simplified...
private static int partition(int[] givenArray, int start, int end, int pivotIndex) {
final int pivot = givenArray[pivotIndex];
int left = start;
int right = end;
while (left < right) {
while (left < givenArray.length && givenArray[left] <= pivot) {
left++;
}
while (right > -1 && givenArray[right] > pivot) {
right--;
}
if (left >= right) {
break;
}
exchange(givenArray, right, left);
}
return right;
}
The one bug I see in your code is your partition routine. In the first exchange call, it is not guaranteed that the right index will always point to a value which is < pivot.
Related
I am trying to implement the median of medians algorithm in Java. The algorithm shall determine the median of a set of numbers. I tried to implement the pseudo code on wikipedia:
https://en.wikipedia.org/wiki/Median_of_medians
I am getting a buffer overflow and don't know why. Due to the recursions it's quite difficult to keep track of the code for me.
import java.util.Arrays;
public class MedianSelector {
private static final int CHUNK = 5;
public static void main(String[] args) {
int[] test = {9,8,7,6,5,4,3,2,1,0,13,11,10};
lowerMedian(test);
System.out.print(Arrays.toString(test));
}
/**
* Computes and retrieves the lower median of the given array of
* numbers using the Median algorithm presented in the lecture.
*
* #param input numbers.
* #return the lower median.
* #throw IllegalArgumentException if the array is {#code null} or empty.
*/
public static int lowerMedian(int[] numbers) {
if(numbers == null || numbers.length == 0) {
throw new IllegalArgumentException();
}
return numbers[select(numbers, 0, numbers.length - 1, (numbers.length - 1) / 2)];
}
private static int select(int[] numbers, int left, int right, int i) {
if(left == right) {
return left;
}
int pivotIndex = pivot(numbers, left, right);
pivotIndex = partition(numbers, left, right, pivotIndex, i);
if(i == pivotIndex) {
return i;
}else if(i < pivotIndex) {
return select(numbers, left, pivotIndex - 1, i);
}else {
return select(numbers, left, pivotIndex + 1, i);
}
}
private static int pivot(int numbers[], int left, int right) {
if(right - left < CHUNK) {
return partition5(numbers, left, right);
}
for(int i=left; i<=right; i=i+CHUNK) {
int subRight = i + (CHUNK-1);
if(subRight > right) {
subRight = right;
}
int medChunk = partition5(numbers, i, subRight);
int tmp = numbers[medChunk];
numbers[medChunk] = numbers[(int) (left + Math.floor((double) (i-left)/CHUNK))];
numbers[(int) (left + Math.floor((double) (i-left)/CHUNK))] = tmp;
}
int mid = (right - left) / 10 + left +1;
return select(numbers, left, (int) (left + Math.floor((right - left) / CHUNK)), mid);
}
private static int partition(int[] numbers, int left, int right, int idx, int k) {
int pivotVal = numbers[idx];
int storeIndex = left;
int storeIndexEq = 0;
int tmp = 0;
tmp = numbers[idx];
numbers[idx] = numbers[right];
numbers[right] = tmp;
for(int i=left; i<right; i++) {
if(numbers[i] < pivotVal) {
tmp = numbers[i];
numbers[i] = numbers[storeIndex];
numbers[storeIndex] = tmp;
storeIndex++;
}
}
storeIndexEq = storeIndex;
for(int i=storeIndex; i<right; i++) {
if(numbers[i] == pivotVal) {
tmp = numbers[i];
numbers[i] = numbers[storeIndexEq];
numbers[storeIndexEq] = tmp;
storeIndexEq++;
}
}
tmp = numbers[right];
numbers[right] = numbers[storeIndexEq];
numbers[storeIndexEq] = tmp;
if(k < storeIndex) {
return storeIndex;
}
if(k <= storeIndexEq) {
return k;
}
return storeIndexEq;
}
//Insertion sort
private static int partition5(int[] numbers, int left, int right) {
int i = left + 1;
int j = 0;
while(i<=right) {
j= i;
while(j>left && numbers[j-1] > numbers[j]) {
int tmp = numbers[j-1];
numbers[j-1] = numbers[j];
numbers[j] = tmp;
j=j-1;
}
i++;
}
return left + (right - left) / 2;
}
}
Confirm n (in the pseudo code) or i (in my code) stand for the position of the median? So lets assume our array is number = {9,8,7,6,5,4,3,2,1,0}. I would call select{numbers, 0, 9,4), correct?
I don't understand the calculation of mid in pivot? Why is there a division by 10? Maybe there is a mistake in the pseudo code?
Thanks for your help.
EDIT: It turns out the switch from iteration to recursion was a red herring. The actual issue, identified by the OP, was in the arguments to the 2nd recursive select call.
This line:
return select(numbers, left, pivotIndex + 1, i);
should be
return select(numbers, pivotIndex + 1, right, i);
I'll leave the original answer below as I don't want to appear to be clever than I actually was.
I think you may have misinterpreted the pseudocode for the select method - it uses iteration rather than recursion.
Here's your current implementation:
private static int select(int[] numbers, int left, int right, int i) {
if(left == right) {
return left;
}
int pivotIndex = pivot(numbers, left, right);
pivotIndex = partition(numbers, left, right, pivotIndex, i);
if(i == pivotIndex) {
return i;
}else if(i < pivotIndex) {
return select(numbers, left, pivotIndex - 1, i);
}else {
return select(numbers, left, pivotIndex + 1, i);
}
}
And the pseudocode
function select(list, left, right, n)
loop
if left = right then
return left
pivotIndex := pivot(list, left, right)
pivotIndex := partition(list, left, right, pivotIndex, n)
if n = pivotIndex then
return n
else if n < pivotIndex then
right := pivotIndex - 1
else
left := pivotIndex + 1
This would typically be implemented using a while loop:
private static int select(int[] numbers, int left, int right, int i) {
while(true)
{
if(left == right) {
return left;
}
int pivotIndex = pivot(numbers, left, right);
pivotIndex = partition(numbers, left, right, pivotIndex, i);
if(i == pivotIndex) {
return i;
}else if(i < pivotIndex) {
right = pivotIndex - 1;
}else {
left = pivotIndex + 1;
}
}
}
With this change your code appears to work, though obviously you'll need to test to confirm.
int[] test = {9,8,7,6,5,4,3,2,1,0,13,11,10};
System.out.println("Lower Median: " + lowerMedian(test));
int[] check = test.clone();
Arrays.sort(check);
System.out.println(Arrays.toString(check));
Output:
Lower Median: 6
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13]
So I tried to write a code to select kth smallest element in a given input integer array using quick sort, but for some reason as you can see in the code below,
public static int partition(int[] input, int first, int end) {
int pivot = input[(first + end)/2];
int i = first - 1;
int j = end + 1;
while (true) {
do {
i++;
} while (input[i] < pivot);
do {
j--;
} while (input[j] > pivot);
if (i < j)
swap(input, i, j);
else
return j;
}
}
public static void swap(int[] input, int i, int j){
int temp = input[i];
input[i] = input[j];
input[j] = temp;
}
public static int select(int[] input, int k){
return mySelect(input, 0, input.length-1, k);
}
public static int mySelect(int[] input, int left, int right, int k){
// If k is smaller than number of elements in array
if (k > 0 && k <= right - left + 1) {
int pos = partition(input, left, right);
if (pos - left == k - 1)
return input[pos];
// If position is larger, recursive call on the left subarray
if (pos - left > k - 1)
return mySelect(input, left, pos-1, k);
// if smaller, recursive call on the right subarray
return mySelect(input, pos+1, right, k-pos+left-1);
}
System.out.println("Invalid k value");
return Integer.MAX_VALUE;
}
public static void main(String[] args){
test2 = new int[]{99, 44, 77, 22, 55, 66, 11, 88, 33};
int[] test2 = new int[]{99, 44, 77, 22, 55, 66, 11, 88, 33};
//testing for selecting kth min
System.out.println("The 1st smallest : " + select(test2, 1));
System.out.println("The 2nd smallest : " + select(test2, 2));
System.out.println("The 3rd smallest : " + select(test2, 3));
System.out.println("The 4th smallest : " + select(test2, 4));
System.out.println("The 6th smallest : " + select(test2, 6));
System.out.println("The 9th smallest : " + select(test2, 9));
}
but my 1st smallest element appears 22, 2nd smallest returns 11, while others values are normal.
can someone please help me find what is the mistake I made?
The problem in your code is in the partition. The do while is the culprit here. You are updating the positions before checking the conditions and that's causing the problem with the last swap operation.
Update your method to this and you will be good to go
public static int partition(int[] input, int first, int end) {
int pivot = input[(first + end)/2];
int i = first;
int j = end;
while (true) {
while (input[i] < pivot) {
i++;
}
while (input[j] > pivot) {
j--;
}
if (i < j)
swap(input, i, j);
else
return j;
}
}
I wrote this code while I was learning quick sort. The mistake I made was in not realizing that
'left' and 'right' are indices in array whereas,
'pivot' is one of the values stored in array
You can study my code below and determine what's wrong in your understanding of the algorithm!!
public class QuickSort
{
public static void main(String[] args)
{
int[] nums = {1,5,9,2,7,8,4,2,5,8,9,12,35,21,34,22,1,45};
quickSort(0,nums.length-1,nums);
//print nums to see if sort is working as expected,omit printing in your case
print(nums);
//now you can write code to select kth smallest number from sorted nums here
}
/**
* left and right are indices in array whereas
* pivot is one of the values stored in array
*/
static int partition(int left, int right , int pivot, int[] nums)
{
int leftIndex = left -1;
int rightIndex = right;
int temp = 0;
while(true)
{
while( nums[++leftIndex] < pivot );
while( rightIndex>0 && nums[--rightIndex] > pivot );
if( leftIndex >= rightIndex ) break;
else//swap value at leftIndex and rightIndex
{
temp = nums[leftIndex];
nums[leftIndex]= nums[rightIndex];
nums[rightIndex] = temp;
}
}
//swap value at leftIndex and initial right index
temp = nums[leftIndex];
nums[leftIndex]= nums[right];
nums[right] = temp;
return leftIndex;
}
static void quickSort( int leftIndex , int rightIndex ,int[] nums)
{
if( rightIndex-leftIndex <= 0 ) return;
else
{
int pivot = nums[rightIndex];
int partitionIndex = partition(leftIndex, rightIndex , pivot,nums);
quickSort(leftIndex,partitionIndex-1,nums);
quickSort(partitionIndex+1,rightIndex,nums);
}
}
static void print(int[] nums)
{
for( int i = 0 ; i < nums.length ; i++ )
{
System.out.print(nums[i]+", ");
}
}
}
I'm trying to implement the randomized selection algorithm that returns the K-th largest element in an array. The algorithm in the code below works when pivot is always set to equal the first element in the array. How do I get the code to work such that it finds the K-th largest using a randomly generated pivot point ?
import java.util.Random;
public class RandomizedKSelection {
private static Random generator = new Random();
public static int partition(int[] A, int start, int end) {
// start = generator.nextInt(end); This Line breaks the code
int pivot = A[start];
int pivotPosition = start++;
while (start <= end) {
// scan for values less than the pivot
while ((start <= end) && (A[start] < pivot)) {
start++;
}
// scan for values greater than the pivot
while ((end >= start) && (A[end] >= pivot)) {
end--;
}
if (start > end) {
// swap the end uncoformed
// element with the pivot
swap(A, pivotPosition, end);
}
else {
// swap unconformed elements:
// start that was not lesser than the pivot
// and end that was not larger than the pivot
swap(A, start, end);
}
}
return end;
}
#SuppressWarnings("unused")
// iterative version
private static int orderStatistic(int[] A, int k, int start, int end) {
int pivotPosition = partition(A, start, end);
while (pivotPosition != k - 1) {
if (k - 1 < pivotPosition) {
end = pivotPosition - 1;
}
else {
start = pivotPosition + 1;
}
pivotPosition = partition(A, start, end);
}
return A[k - 1];
}
public static int kthLargest(int[] A, int k) {
return orderStatistic(A, A.length - k + 1, 0, A.length - 1);
}
public static void swap(int[] A, int i, int j){
int temp = A[i];
A[i]= A[j];
A[j] = temp;
}
}
I've got a `partition implementation from wikibooks. I changed your code to use 0-based indices (you can find examples for 0-based indices more easily), you can wrap them if you like (see kthLargest1Based). Small randomized test arguments the validity of the algorithm.
import java.util.Arrays;
import java.util.Random;
public class RandomizedKSelection {
private static Random generator = new Random();
private static int partition(int[] array, int begin, int end) {
int index = begin + generator.nextInt(end - begin + 1);
int pivot = array[index];
swap(array, index, end);
for (int i = index = begin; i < end; ++ i) {
if (array[i] <= pivot) {
swap(array, index++, i);
}
}
swap(array, index, end);
return (index);
}
// iterative version
private static int orderStatistic(int[] A, int k, int start, int end) {
int pivotPosition = partition(A, start, end);
while (pivotPosition != k) {
if (k < pivotPosition) {
end = pivotPosition - 1;
} else {
start = pivotPosition + 1;
}
pivotPosition = partition(A, start, end);
}
return A[k];
}
public static int kthLargest(int[] A, int k) {
return orderStatistic(A, A.length - k - 1, 0, A.length - 1);
}
public static int kthLargest1Based(int[] A, int k) {
return kthLargest(A, k - 1);
}
public static int kthLargestSafe(int[] A, int k) {
Arrays.sort(A);
return A[A.length - k - 1];
}
public static void swap(int[] A, int i, int j) {
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
public static void main(String[] args) {
Random random = new Random();
for (int i = 0; i < 1000000; i++) {
int[] A = new int[1 + random.nextInt(1000)];
int max = 1 + random.nextInt(2 * A.length);
for (int j = 0; j < A.length; j++) {
A[j] = random.nextInt(max);
}
int k = random.nextInt(A.length);
if (RandomizedKSelection.kthLargest(A, k) != RandomizedKSelection.kthLargestSafe(A, k)) {
System.out.println("BUG");
}
}
}
}
I am trying to spit an int array and add up the elements but im getting errors. Here is my code. I can't figure it out.
int arraySize = 10;
int[] numsToSum = new int[arraySize];
for (int i = 0; i < arraySize; i++)
{
numsToSum[i] = i * 3;
System.out.println(numsToSum[i]);
}
int sum3 = sumArray3(numsToSum, 0, arraySize - 1);
System.out.println(sum3);
public static int sumArray3(int [] array, int start, int end)
{
int results = 0;
int mid = (start + end)/2;
if(array.length > 0)
{
results += sumArray3(array, start + 1, mid) + sumArray3(array, mid +1, end);
}
return results;
You don't have a recursion termination condition, in this case i'd assume you want to check if the start and end counters for the array are the same. Check the code below.
class StackOv {
public static void main(String[] args) {
int arraySize = 10;
int[] numsToSum = new int[arraySize];
for (int i = 0; i < arraySize; i++)
{
numsToSum[i] = i * 3;
System.out.println(numsToSum[i]);
}
int sum3 = sumArray3(numsToSum, 0, arraySize - 1);
System.out.println(sum3);
}
public static int sumArray3(int [] array, int start, int end)
{
int results = 0;
if(start == end)
return array[start];
int mid = (start + end)/2;
if(array.length > 0) {
results += sumArray3(array, start, mid) + sumArray3(array, mid +1, end);
}
return results;
}
}
I finally figured it out. Thanks for your help. I didn't have a base like you said.
public static int sumArray3(int [] array, int start, int end)
{
int results = 0;
int mid = (start + end)/2;
if(start < end)
{
results += sumArray3(array, start, mid) + sumArray3(array, mid +1, end);
}
else
results = array[start];
return results;
}
It looks like you don't have a "base-case", where you return a solid value. Your function as-is will always return 0.
At a guess, I would say you should start by changing it so that you check whether start+1 <= end and if so, returning your current value; if not returning the value at that index, with an else:
else {
results = array[start];
}
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;
}
}