I going to do searching the value in the array, did I need to create a method to handle it? For example, the array logged 32,21,13,44,22, and I going to find 22 of the comparison. How can I implement this?
public class binarySearch {
public static void main(String [] args) {
int i = binarySearch(0, new int[]{32,21,13,44,22});
System.out.println("Iterations: " + i);
}
public static int binarySearch(int key, int[] array) {
int left = 0;
int mid;
int right = array.length - 1;
int i = 0;
while (left <= right) {
mid = (left + right) / 2;
int comp = Integer.compare(key, array[mid]);
i++;
if (comp < 0) {
right = mid - 1;
} else if (comp > 0) {
left = mid + 1;
} else {
break; // success
}
}
return i;
}
}
My final answer is here. May help you all in the future.
public static int binarySearch(int key, int[] array) {
int left = 0;
int mid;
int right = array.length - 1;
int i = 0;
while (left <= right) {
mid = (left + right) / 2;
int comp = Integer.compare(key, array[mid]);
i++;
if (comp < 0) {
right = mid - 1;
} else if (comp > 0) {
left = mid + 1;
} else {
break; // success
}
}
return i;
}
If you have shuffled array, all you can do is go through an array and find your number.
BinarySearch works only with sorted array. I think your solution could look like this:
public static int binarySearch(int[] arr, int key) {
Arrays.sort(arr);
return Arrays.binarySearch(arr, key);
}
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;
}
My problem statement is this -
Find the count of numbers in a sorted array that are less than a given number, and this should be done efficiently with respect to time. I wrote a program using binary search that gets the count but time complexity wise it's failing. Need help in achieving this.
import java.util.Arrays;
public class SortedSearch {
public static int countNumbers(int[] sortedArray, int lessThan) {
if(sortedArray.length ==1 || sortedArray.length == 0) {
return singleElement(sortedArray, lessThan);
}
else {
return binarySearch(sortedArray, lessThan);
}
}
public static int singleElement(int[] sortedArray, int searchVal) {
if(sortedArray.length == 0) {
return 0;
}
if(sortedArray[0] < searchVal) {
return 1;
}
return 0;
}
private static int binarySearch(int[] sortedArray, int searchVal) {
int low = 0;
int high = (sortedArray.length)-1;
int mid = (low + high)/2;
if((sortedArray.length == 0) || (sortedArray[0] > searchVal)) {
return 0;
}
if(sortedArray[high] < searchVal) {
return sortedArray.length;
}
if(sortedArray[high] == searchVal) {
return sortedArray.length-1;
}
if(sortedArray[mid] < searchVal) {
int newLow = low;
int newHigh = calculateNewHigh(sortedArray, newLow, 0, searchVal);
int[] newArray = Arrays.copyOfRange(sortedArray, newLow, newHigh+1);
return newArray.length;
}
else {
int newLow = low;
int newHigh = mid;
int[] newArray = Arrays.copyOfRange(sortedArray, newLow, newHigh+1);
return binarySearch(newArray, searchVal);
}
}
private static int calculateNewHigh(int[] sortedArray, int low, int previousHigh, int searchVal) {
int newHigh = previousHigh + (sortedArray.length-low)/2;
if(sortedArray[newHigh] < searchVal) {
newHigh = calculateNewHigh(sortedArray, newHigh, newHigh, searchVal);
}
if(sortedArray[newHigh] == searchVal) {
newHigh--;
}
if(sortedArray[newHigh] > searchVal) {
newHigh--;
}
return newHigh;
}
public static void main(String[] args) {
System.out.println(SortedSearch.countNumbers(new int[] { 1, 3, 5, 7 }, 4));
}
}
Since you're using Arrays anyway, way not use the Arrays.binarySearch(int[] a, int key) method, instead of attempting to write your own?
public static int countNumbers(int[] sortedArray, int lessThan) {
int idx = Arrays.binarySearch(sortedArray, lessThan);
if (idx < 0)
return -idx - 1; // insertion point
while (idx > 0 && sortedArray[idx - 1] == lessThan)
idx--;
return idx; // index of first element with given value
}
The while loop1 is necessary because the javadoc says:
If the array contains multiple elements with the specified value, there is no guarantee which one will be found.
1) This loop is not optimal if e.g. all values are the same, see e.g. Finding multiple entries with binary search
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;
}
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);
}
}
}