Binary Search Using Recusion - java

I am trying to create a binary search algorithm using recursion in Java, when debugging everything seems to be okay up until it finds the value and should return the index of the key needed. However, for some reason it skips the return statement and goes to the bottom return statement.
public int binSearch(int key, int L, int R) {
int mid =(R + L)/2;
if (R < L) {
return -1;
}
if (A[mid] == key) {
return mid;
}
if (key > A[mid]) {
binSearch(key, mid + 1, R);
}
if (key < A[mid]) {
binSearch(key, L, mid - 1);
}
return -1;
}

I was able to salvage this from an old post. I know it doesnt fix your problem, but it shows you another way to solving this problem.
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);
}
}

You are missing some return statements (when you are invoking binSearch recursively)
public int binSearch(int key, int L, int R) {
int mid =(R + L)/2;
if (R < L) {
return -1;
}
if (A[mid] == key) {
return mid;
}
if (key > A[mid]) {
return binSearch(key, mid + 1, R);
}
if (key < A[mid]) {
return binSearch(key, L, mid - 1);
}
return -1;
}

Related

Searching in a Bitonic Array becomes infinite loop

I am trying to write a searching algorithm in a bitonic array. Please take a look in the ascending function, where I am printing 'lo'. When I run this code, it keeps print that 'lo' number. I don't understand why it becomes infinite loop there. Here is my code:
public class bitonicArray {
public int ascending(int[] a, int key, int lo, int hi) {
int mid = lo+(hi-lo)/2;
while(lo<=hi) {
if (key<a[mid]) hi = mid-1;
else if (key>a[mid]) {
lo=mid+1;
System.out.println(lo);
}
else return mid;
}
return -1;
}
public int descending(int[] a, int key, int lo, int hi) {
int mid=lo+(hi-lo)/2;
while(lo<=hi) {
if(key<a[mid]) lo = mid+1;
else if(key>a[mid]) {
hi = mid-1;
}
else return mid;
}
return -1;
}
public int bitonicPoint(int[] a) {
int hi = a.length-1;
int lo = 0;
int mid = (hi-lo)/2;
while(mid<=hi) {
if (a[mid-1] < a[mid] && a[mid+1]>a[mid]) mid = mid + 1;
else if (a[mid-1] > a[mid] && a[mid+1]<a[mid]) mid = mid - 1;
else if (a[mid-1]<a[mid] && a[mid+1]<a[mid]) return mid;
}
return -1;
}
public int ind(int[] a, int key) {
int lo = 0;
int hi = a.length-1;
int bit = bitonicPoint(a);
int asc = ascending(a, key, lo, bit-1);
System.out.println(asc);
int desc = descending(a, key, bit+1, hi);
if (asc != -1) {
System.out.println(asc);
return asc;
}
else if (desc != -1) return desc;
else return bit;
}
public static void main(String[] args) {
int n[]= {1,3,4,6,9,14,11,7,2,-4,-9};
bitonicArray ba = new bitonicArray();
System.out.println(ba.ind(n, 6));
}
}
Please help with this. I am pretty new in Java. I am a Python user. Trying to learn Java.
In this part of code fragment you are not updating your mid value
public int ascending(int[] a, int key, int lo, int hi) {
int mid = lo+(hi-lo)/2;
while(lo<=hi) {
if (key<a[mid]) hi = mid-1;
else if (key>a[mid]) {
lo=mid+1;
System.out.println(lo);
}
else return mid;
}
return -1;
}
Initially when this function is called from ind function , value of lo is 0 and hi is 4.
So, mid value is 2.
Because of this in while loop it goes in this part :
else if (key>a[mid]) {
lo=mid+1;
System.out.println(lo);
}
Hence you get your first lo value printed , but then you have updated lo value but not
mid.
Because of which every time mid is at 2 and in while loop each time it goes in same code fragment. You need to update value of mid because it is dependent on lo and hi and in the above else if part you have updated value of lo.
Corrected code is :
public int ascending(int[] a, int key, int lo, int hi) {
int mid = 0;
while(lo<=hi) {
mid = lo+(hi-lo)/2;
if (key<a[mid]) hi = mid-1;
else if (key>a[mid]) {
lo=mid+1;
System.out.println(lo);
}
else return mid;
}
return -1;
}

What is the size above depth of BST

This is what I have so far. I need to computes the size of the tree above at depth k.
public static int above(Node t, int k) {
if (t == null) { return 0; }
if (t.key > k)
return (above(t.left, k - 1) + above(t.right, k - 1) + 1);
else {
return above(t.left, k - 1) + above(t.right, k - 1);
}
}
EDIT: This code works and computes the size of the tree at depth k.
public static int at(Node t, int k) {
if(t == null) return 0;
if(k == 0) return 1;
return at(t.left, k - 1) + at(t.right, k - 1);
}
I would of thought something more like this would do it... but maybe I don't understand the problem correctly.
public static int above(Node t, int k) {
if (t == null) { return 0; }
if (k > 0) {
return (above(t.left, k - 1) + above(t.right, k - 1) + 1);
} else {
return 1;
}
}
This code computes the tree size till depth k where root is at depth 1.
static int depth=0;
static int tree_size=0,k=3;
private static void inorder(Node head) {
if(head!=null){
depth++;
inorder(head.left);
if(depth<=k)
tree_size++;
inorder(head.right);
depth--;
}
}

find the index in a sorted array

it's a basic problem that given a sorted array and a target value, find the index if the target is found. If not, return the index where it would be if it were inserted in order.
Here is my method:
public int searchInsert1(int[] A, int target) {
if (A == null || A.length == 0)
return 0;
return search(A, target, 0, A.length);
}
public int search(int[] a, int target, int s, int e) {
if (s == e)
return s;
int mid = (s + e) / 2;
if (a[mid] == target) {
return mid;
} else if (target < a[mid]) {
return search(a, target, 0, mid - 1);
} else {
return search(a, target, mid, e);
}
}
somehow, it always returns the wrong index value. However, if I change the if else part as the following, it works:
if (a[mid] == target) {
return mid;
} else if (target > a[mid]) {
return search(a, target, mid + 1, e);
} else {
return search(a, target, 0, mid);
}
can anyone help me with it in detail? Thanks so much in advance
Use this method
public int search(int[] a, int target, int s, int e) {
int low = s;
int high = e- 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = a[mid];
if (midVal < target)
low = mid + 1;
else if (midVal > target)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
Your code has errors in these parts:
1. you have set end index wrong, it should be :A.length - 1;
2. your return value in the condition part is wrong,the return value in your "else" part should be: search(a, target, 0, mid+1, e);
Correct code should be:
public int searchInsert1(int[] A, int target) {
if (A == null || A.length == 0)
return 0;
// check if target is larger than the largest value or smaller than the smallest value
if (target < A[0])
return 0;
else if (target > A[A.length-1])
return A.length-1;
return search(A, target, 0, A.length-1);
}
public int search(int[] a, int target, int s, int e) {
if (s == e)
return s;
int mid = (s + e) / 2;
if (a[mid] == target) {
return mid;
} else if (target < a[mid]) {
return search(a, target, 0, mid - 1);
} else {
return search(a, target, mid+1, e);
}
}
Here is my simplest solution in Java
public static int search(int[] a, int target) {
for (int i = 0; i < a.length; i++) {
if (a[i] == target) {
return i;
}
}
return -1;
}

Using a recursive binary search in an InsertInOrder

I'm reading in a text file of unsorted numbers
static void insertInOrder( int[] arr, int cnt, int newVal )
{
int belongs = -( bSearch( arr, 0, arr.length-1, newVal)) - 1;
{
for ( int i = cnt; i >= belongs+1 ; --i)
{
arr[i] = arr[i-1];
}
arr[belongs] = newVal;
}
}
// We do not need to pass in count. The incoming lo and hi define the range
public static int bSearch(int[] a, int lo, int hi, int key)
{
int mid = (lo+hi)/2;
if(lo>hi)
return -1;
else if (a[mid]==key)
return mid;
else if (a[mid]<key)
return bSearch(a, mid+1, hi, key);
else
return bSearch(a, lo, mid-1, key);
}
The binary search is working, but my insertinorder isn't putting the numbers in ascending order and I can't figure out why. It's just printing the list out backwards. And this has to be done using a recursive binary search in an insertinorder.
Have you copied the latest code in to the question ???.
One obvious problem is:
int belongs = -( bSearch( arr, 0, arr.length-1, newVal)) - 1;
the method bSearch returns -1 when a value is not found in the array. This will give an insertion point of -2 when newValue is not found. You need to change bSearch to return both wether the item was found and the position. Two options
Create (and return) a new class
private class FoundResult {
boolean found = true;
int position;
}
When not found; return -hi-1
i.e. in bSearch some thing like:
if(lo>hi)
return -hi-1;
For option 1, the code will be roughly (i have not tested this):
static void insertInOrder( int[] arr, int cnt, int newVal ) {
int belongs = bSearch( arr, 0, arr.length-1, newVal)).position ;
for ( int i = cnt; i >= belongs+1 ; --i) {
arr[i] = arr[i-1];
}
arr[belongs] = newVal;
}
// We do not need to pass in count. The incoming lo and hi define the range
public static FoundResult bSearch(int[] a, int lo, int hi, int key)
{
int mid = (lo+hi)/2;
FoundResult ret;
if(lo>hi) {
ret = new FoundResult();
ret.found = false;
ret.position = hi;
return ret;
} else if (a[mid]==key) {
ret = new FoundResult();
ret.position = hi;
return ret;
} else if (a[mid]<key) {
return bSearch(a, mid+1, hi, key);
} else {
return bSearch(a, lo, mid-1, key);
}
For option 2 the code is roughly:
static void insertInOrder( int[] arr, int cnt, int newVal ) {
int belongs = bSearch( arr, 0, arr.length-1, newVal)) ;
if (belongs < 0) {
belongs = -1 - belongs ;
}
for ( int i = cnt; i >= belongs+1 ; --i) {
arr[i] = arr[i-1];
}
arr[belongs] = newVal;
}
// We do not need to pass in count. The incoming lo and hi define the range
public static int bSearch(int[] a, int lo, int hi, int key)
{
int mid = (lo+hi)/2;
FoundResult ret;
if(lo>hi) {
return - hi - 1;
} else if (a[mid]==key) {
return hi;
} else if (a[mid]<key) {
return bSearch(a, mid+1, hi, key);
} else {
return bSearch(a, lo, mid-1, key);
}

Segment tree java implementation [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 6 years ago.
Improve this question
Do you know a good implementation of a (binary) segment tree in Java?
public class SegmentTree {
public static class STNode {
int leftIndex;
int rightIndex;
int sum;
STNode leftNode;
STNode rightNode;
}
static STNode constructSegmentTree(int[] A, int l, int r) {
if (l == r) {
STNode node = new STNode();
node.leftIndex = l;
node.rightIndex = r;
node.sum = A[l];
return node;
}
int mid = (l + r) / 2;
STNode leftNode = constructSegmentTree(A, l, mid);
STNode rightNode = constructSegmentTree(A, mid+1, r);
STNode root = new STNode();
root.leftIndex = leftNode.leftIndex;
root.rightIndex = rightNode.rightIndex;
root.sum = leftNode.sum + rightNode.sum;
root.leftNode = leftNode;
root.rightNode = rightNode;
return root;
}
static int getSum(STNode root, int l, int r) {
if (root.leftIndex >= l && root.rightIndex <= r) {
return root.sum;
}
if (root.rightIndex < l || root.leftIndex > r) {
return 0;
}
return getSum(root.leftNode, l, r) + getSum(root.rightNode, l, r);
}
/**
*
* #param root
* #param index index of number to be updated in original array
* #param newValue
* #return difference between new and old values
*/
static int updateValueAtIndex(STNode root, int index, int newValue) {
int diff = 0;
if(root.leftIndex==root.rightIndex && index == root.leftIndex) {
// We actually reached to the leaf node to be updated
diff = newValue-root.sum;
root.sum=newValue;
return diff;
}
int mid = (root.leftIndex + root.rightIndex) / 2;
if (index <= mid) {
diff= updateValueAtIndex(root.leftNode, index, newValue);
} else {
diff= updateValueAtIndex(root.rightNode, index, newValue);
}
root.sum+=diff;
return diff;
}
}
This has been implemented within the open source Layout Management SW Package project
Here is a link to the sub package
You might find the code useful. I have neither verified it nor run it and I cannot find the license the code is provided under from a quick search of the code and website so Caveat Emptor.
You may be able to contact the authors but the last activity appears to have been August 2008.
Here it is:
import java.util.Scanner;
public class MinimumSegmentTree {
static Scanner in = new Scanner(System.in);
public static void main(String[] args) {
final int n = in.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = in.nextInt();
}
int sizeOfSegmentTree = (int) Math.pow(2, Math.ceil(Math.log10(n) / Math.log10(2)));
sizeOfSegmentTree = 2*sizeOfSegmentTree-1;
// System.out.println(sizeOfSegmentTree);
int[] segmentTree = new int[sizeOfSegmentTree];
formSegmentTree(a, segmentTree, 0, n-1, 0);
// for(int i=0; i<sizeOfSegmentTree; i++){
// System.out.print(segmentTree[i]+" ");
// }
// System.out.println();
final int q = in.nextInt();
for (int i = 0; i < q; i++) {
int s, e;
s = in.nextInt();
e = in.nextInt();
int minOverRange = getMinimumOverRange(segmentTree, s, e, 0, n-1, 0);
System.out.println(minOverRange);
}
}
private static int getMinimumOverRange(int[] segmentTree, int qs, int qe, int s, int e, int pos) {
if (qs <= s && qe >= e) {
return segmentTree[pos];
}
if (qs > e || s > qe) {
return 10000000;
}
int mid = (s + e) / 2;
return Math.min(getMinimumOverRange(segmentTree, qs, qe, s, mid, 2 * pos + 1),
getMinimumOverRange(segmentTree, qs, qe, mid+1, e, 2 * pos + 2));
}
private static void formSegmentTree(int[] a, int[] segmentTree, int s, int e, int pos) {
if (e - s == 0) {
segmentTree[pos] = a[s];
return;
}
int mid = (s + e) / 2;
formSegmentTree(a, segmentTree, s, mid, 2 * pos + 1);
formSegmentTree(a, segmentTree, mid+1, e, 2 * pos + 2);
segmentTree[pos] = Math.min(segmentTree[2 * pos + 1], segmentTree[2 * pos + 2]);
}
}
Algo and unit tests:
public class NumArrayTest {
#Test
public void testUpdateSumRange_WithEmpty() throws Exception {
NumArray numArray = new NumArray(new int[]{});
assertEquals(0, numArray.sumRange(0, 0));
}
#Test
public void testUpdateSumRange_WithSingleton() throws Exception {
NumArray numArray = new NumArray(new int[]{1});
assertEquals(1, numArray.sumRange(0, 0));
numArray.update(0, 2);
assertEquals(2, numArray.sumRange(0, 0));
}
#Test
public void testUpdateSumRange_WithPairElements() throws Exception {
NumArray numArray = new NumArray(new int[]{1,2,3,4,5,6});
assertEquals(12, numArray.sumRange(2, 4));
numArray.update(3, 2);
assertEquals(10, numArray.sumRange(2, 4));
}
#Test
public void testUpdateSumRange_WithInPairElements() throws Exception {
NumArray numArray = new NumArray(new int[]{1,2,3,4,5,6,7});
assertEquals(12, numArray.sumRange(2, 4));
numArray.update(3, 2);
assertEquals(10, numArray.sumRange(2, 4));
}
}
public class NumArray {
private final Node root;
private static class Node {
private final int begin;
private final int end;
private final Node left;
private final Node right;
private int sum;
public Node(int begin, int end, int sum, Node left, Node right) {
this.begin = begin;
this.end = end;
this.sum = sum;
this.left = left;
this.right = right;
}
public boolean isSingle() {
return begin == end;
}
public boolean contains(int i) {
return i >= begin && i <= end;
}
public boolean inside(int i, int j) {
return i <= begin && j >= end;
}
public boolean outside(int i, int j) {
return i > end || j < begin;
}
public void setSum(int sum) {
this.sum = sum;
}
}
public NumArray(int[] nums) {
if (nums.length == 0) {
root = null;
} else {
root = buildNode(nums, 0, nums.length - 1);
}
}
private Node buildNode(int[] nums, int begin, int end) {
if (begin == end) {
return new Node(begin, end, nums[begin], null, null);
} else {
int mid = (begin + end) / 2 + 1;
Node left = buildNode(nums, begin, mid - 1);
Node right = buildNode(nums, mid, end);
return new Node(begin, end, left.sum + right.sum, left, right);
}
}
public void update(int i, int val) {
if (root == null) {
return;
}
if (!root.contains(i)) {
throw new IllegalArgumentException("i not in range");
}
update(root, i, val);
}
private int update(Node node, int i, int val) {
if (node.isSingle()) {
node.setSum(val);
} else {
Node nodeToUpdate = node.left.contains(i) ? node.left : node.right;
int withoutNode = node.sum - nodeToUpdate.sum;
node.setSum(withoutNode + update(nodeToUpdate, i, val));
}
return node.sum;
}
public int sumRange(int i, int j) {
if (root == null) {
return 0;
}
return sumRange(root, i, j);
}
private int sumRange(Node node, int i, int j) {
if (node.outside(i, j)) {
return 0;
} else if (node.inside(i, j)) {
return node.sum;
} else {
return sumRange(node.left, i, j) + sumRange(node.right, i, j);
}
}
}

Categories