java.lang.ArrayIndexOutOfBoundsException error when doing a binary search? - java

i am getting a little problem and i really do not know why. i am trying to program to search for a number input by the user using a binary searching method. it works well when the number in the middle of the array is searched for but when i attempt to search any other number am getting an error. here is my code.
import java.util.Scanner;
public class Main {
public static void main(String args[])
{
//declaring array
int array[] = {12,23,34,45,56,67,78,89};
//declaring variables
int search = 0;
Scanner input = new Scanner(System.in);
System.out.print("\n Enter: ");
search = input.nextInt();
binarySearch(array, search);
}//end of main
static public void binarySearch(int[] array, int search)
{
int begin = 0;
int end = array.length-1;
int mid = 0;
boolean found = false;
while(!found)
{
mid = (begin + end)/2;
if(array[mid] == search)
{
found = true;
search = array[mid];
}
else if(array[mid] < search)
{
begin = array[mid+1];
}
else if(array[mid] > search)
{
end = array[mid-1];
}
}//end of while loop
//if(!found)
//return ("BOOHOO your search was not found");
System.out.print("Yippee i found "+ search + " at index " + mid);
}
}//end of class

When you don't find a search, you need to reset your begin and end pointers to the indexes and not on the values on those indexes i.e.
while(!found)
{
mid = (begin + end)/2;
if(array[mid] == search)
{
found = true;
}
else if(array[mid] < search)
{
begin = mid+1;
}
else if(array[mid] > search)
{
end = mid-1;
}
}//end of while loop

Related

Binary Search only returns one statement

I'm new to binary searches and I tried a program that would find the position of a value inputted by a user. My code however only seems to return a low=-1 value which leads to the program saying "the value was not found". I think I did something wrong with my binary search code, but I am not experienced with these and may have missed something? Here's my code for the binary search:
static public int search (int[]numbers,int target, int count)
{
int high = numbers.length;
int low = -1;
int middle = (high+low)/2;
while(high-low>1)
{
count++;
middle = (high+low)/2;
if(numbers[middle]>target)
{
high = middle;
}
else if(numbers[middle]<target)
{
low = middle;
}
else if(numbers[middle] == target)
{
break;
}
System.out.println(numbers[middle]);
System.out.println(middle);
}
if(low == -1 || numbers[low]!=target)
{
low=-1;
return low;
}
else
{
return low;
}
}
And here is part of the code which asks users for an input:
public static void main(String[] args) throws IOException {
DataInputStream input = new DataInputStream(System.in);
int [] numbers = new int [50000];
int target;
int count=0;
try
{
BufferedReader br = new BufferedReader(new FileReader("randNums.txt"));
for(int i=0;i<50000;i++)
{
numbers[i]=Integer.parseInt(br.readLine());
}
br.close();
Arrays.sort(numbers);
System.out.print("Choose a number between 1-100000000 to search for: ");
target = Integer.parseInt(input.readLine());
int low = search(numbers, target, count);
if(low==-1)
{
System.out.println("The number was not on the list.");
}
else
{
System.out.println("The number is at position " + low);
System.out.println("It took " + count + " comparisons to find the number.");
}
}
Your search function has some issues. The implementation of the binary search in the search function should be like this:
static public int search (int[]numbers,int target, int count)
{
int high = numbers.length-1;
int low = 0;
int middle = (high+low)/2;
while(high>=low)
{
count++;
middle = (high+low)/2;
if(numbers[middle]==target)
{
return middle;
}
else if(numbers[middle]<target)
{
low = middle+1;
}
else if(numbers[middle]>target)
{
high=middle-1;
}
System.out.println(numbers[middle]);
System.out.println(middle);
}
return -1;
}

Binary search algorithm isn't returning variable

I'm very new to binary search and I attempted a code that would read values from a document and then the user can input a number to search for from the document, and through binary search, the number would be found. I'm having trouble now because the "low" variable that I initialize in the binary search section of my code is not being returned to my main code and there's an error that says "low can not be resolved to a variable".
Here is the code for my binary search:
static public int search (int[]numbers,int target, int count)
{
int high = numbers.length;
int low = -1;
int middle = (high+low)/2;
while(high-low>1)
{
count++;
middle = (high+low)/2;
if(numbers[middle]>target)
{
high = middle;
}
else if(numbers[middle]<target)
{
low = middle;
}
else
{
break;
}
System.out.println(numbers[middle]);
System.out.println(middle);
}
if(low == -1 || numbers[low]!=target)
{
low=-1;
return low;
}
else
{
return low;
}
}
And here is the code from my main code. The part with the if statements is where the error is showing up:
public static void main(String[] args) throws IOException {
DataInputStream input = new DataInputStream(System.in);
int [] numbers = new int [50000];
int target;
int count=0;
try
{
BufferedReader br = new BufferedReader(new FileReader("randNums.txt"));
for(int i=0;i<50000;i++)
{
numbers[i]=Integer.parseInt(br.readLine());
}
br.close();
Arrays.sort(numbers);
System.out.print("Choose a number between 1-100000000 to search for: ");
target = Integer.parseInt(input.readLine());
search(numbers, target,count);
if(low==-1)
{
System.out.println("The number was not on the list.");
}
else
{
System.out.println("The number is at position " + low);
System.out.println("It took " + count + " comparisons to find the number.");
}
}
You have to initialize low in main:
int low=search(numbers, target,count);
I have Already resolved this algorithm.
Try my code :
public static int guessNumber(int number) {
int first = 0;
int last = 1_000_000;
if (verify(first) == 0) {
count++;
return first;
}
if (verify(last) == 0) {
count++;
return last;
}
while (last > first && count <= 50) {
count += 1;
// get the middle of the range
int middle = (first + last) / 2;
if (verify(middle) == 0) {
return middle;
}
if (verify(middle) == 1) {
first = middle + 1;
if (verify(first) == 0) {
return first;
}
}else {
last = middle - 1;
if (verify(last) == 0)
return last;
}
}
return 0;
}
//Function verify(integer) => integer
public static int verify(int guess){
if (numberTobeGuessed > guess ) {
return 1;
}else if (numberTobeGuessed < guess) {
return -1;
}
return 0;
}
I recently found a solution for lazy peoples like me use below code
int position = Arrays.binarySearch(numbers , target);
here no need to sort, and array variable number integer variable target.

FIbonacci series using recursion error?

public class Fibonacci2 {
static int fib(int n) {
if(n==1 || n==2) {
return(1);
}
return fib((n-1)+fib(n-2));
}
// Stackoverflow error //
public static void main(String[] args) {
int i, n = 7;
for(i=1; i<=n; i++)
System.out.println("FIbonaci series" + fib(i));
}
}
This program suffer from runtime exception (stackoverflow) please tell how to deal with it.
You step through the code in your debugger and you will see that
return fib((n-1)+fib(n-2));
should be
return fib(n-1) + fib(n-2);
as what you have is like
return fib(fib(n-2));
which quickly creates very high levels of recursion.
replace fib((n-1)+fib(n-2)) with fib(n-1)+fib(n-2).
May be it will help you
public static void fib(int initial, int current, int n) {
int sum = 0;
sum = initial + current;
if (initial == 0) {
System.out.print(current + " ");
}
System.out.print(sum + " ");
initial = current;
current = sum;
if (n > 2) {
fib(initial, current, n - 1);
}
}

Binary search doesn't return anything

I'm trying to run a binary search where the user can input a value and my binary search method will return a part number and price but it doesn't return anything when any value is entered. The search is used on parallel arrays. I call the method below in main.
public int binSearch(int target)
{
int first = 0;
int last = numCount -1;
boolean found = false;
while(first <= last && !found)
{
mid = (first + last)/2;
if(partNum[mid]==target)
{
found = true;
}
else if(partNum[mid]<target)
{
first = mid +1;
}
else if(partNum[mid]>target)
{
last = mid -1;
}
else if(!found)
{
mid = -1;
}
return mid;
}
Here is the code that calls the method in the main class.
index = inputDevice.nextInt();
while(inventoryArray.binSearch(index) >= 0);
{
System.out.printf("Binary search found part #%d. The price is $%d\n", index, inventoryArray.binSearch(index));
Your array is supposed to be sorted.
You need to set the return outside the loop
and when the last condition is reached ( which is supposed to mean that the target is not in the sorted array) you should break after setting mid = -1 , and no need to check if its found
while(first <= last && !found)
{
mid = (first + last)/2;
if(partNum[mid]==target)
{
found = true;
}
else if(partNum[mid]<target)
{
first = mid +1;
}
else if(partNum[mid]>target)
{
last = mid -1;
}
else
{
mid = -1;
break;
}
}
return mid;

Convert a string like 2,4,5,6,7,8,10,12,14,15,16 to 2,4-8,10,12,14-16

I want to convert a string input like 2,3,6,7,8,10,12,14,15,16 to 2-3,6-8,10,12,14-16 using java
I tried using the below code
Vector ar=new Vector();
int lastadded=0;
String ht="";
String [] strarray=str.split(",");
strarray=sortArray(strarray);
Vector intarray=new Vector();
for(int i=0;i<strarray.length;i++)
{
int temp=1;
for(int j=1;j<=intarray.size();j++)
{
if(Integer.parseInt(strarray[i])==Integer.parseInt(intarray.get(j-1).toString()))
{
temp=0;
}
}
if(temp==1)
{
intarray.add(Integer.parseInt(strarray[i]));
ar.add(Integer.parseInt(strarray[i]));
}
}
ht="";
String strdemo="";
for(int i=0;i<intarray.size();i++)
{
if(ht=="")
{
ht=ar.get(i)+"";
lastadded=i;
}
else
{
strdemo=(String)ht;
if(strdemo.length()==ar.get(0).toString().length())
{
if(Integer.parseInt(strdemo.substring(0))==Integer.parseInt(ar.get(i).toString())-1)
{
strdemo=strdemo+"-"+ar.get(i);
lastadded=Integer.parseInt(ar.get(i).toString());
ht=strdemo;
}
else
{
strdemo=strdemo+","+ar.get(i);
lastadded=Integer.parseInt(ar.get(i).toString());
ht=strdemo;
}
}
else if(strdemo.length()==3)
{
strdemo=(String)ht;
if(Integer.parseInt(strdemo.substring(strdemo.length()-1,strdemo.length()))==Integer.parseInt(ar.get(i).toString())-1)
{
strdemo=strdemo.substring(0,strdemo.length()-2)+"-"+Integer.parseInt(ar.get(i).toString());
lastadded=Integer.parseInt(ar.get(i).toString());
ht=strdemo;
}
else
{
strdemo=strdemo+","+Integer.parseInt(ar.get(i).toString());
lastadded=Integer.parseInt(ar.get(i).toString());
ht=strdemo;
}
}//Else IF
else{
strdemo=(String)ht;
int de=1;
int ddd=lastadded;
if(ddd==Integer.parseInt(ar.get(i).toString())-1)
{
int lastaddedlen=(lastadded+"").length();
String symbol=strdemo.substring(strdemo.length()-lastaddedlen-1,strdemo.length()-lastaddedlen);
if(symbol.equalsIgnoreCase("-"))
strdemo=strdemo.substring(0,strdemo.length()-lastaddedlen-1)+"-"+Integer.parseInt(ar.get(i).toString());
else
strdemo=strdemo+"-"+Integer.parseInt(ar.get(i).toString());
lastadded=Integer.parseInt(ar.get(i).toString());
ht=strdemo;
}
else
{
strdemo=strdemo+","+Integer.parseInt(ar.get(i).toString());
lastadded=Integer.parseInt(ar.get(i).toString());
ht=strdemo;
}
}
}
}
Here sortArray function sorts the array descending and returns
protected static String[] sortArray(String ss[])
{
String temp;
for(int i=0;i<ss.length;i++)
{
for(int j=0;j<ss.length;j++)
{
if(Integer.parseInt(ss[i])<Integer.parseInt(ss[j]))
{
temp=ss[i];
ss[i]=ss[j];
ss[j]=temp;
}
}
}
return ss;
}
I am not getting consistant results for some inputs for example for the below case
2,3,6,7,8,10,12,14,15,16 it gives 2-3,6-8,10,12,14-16 (which is correct)
while for 2,4,5,6,7,8,10,12,14,15,16 it gives 2-8,10,12,14-16 (which actually should have been 2,4-8,10,12,14-16)
Where does the code go inconsistent is what I need to find out..
This is pretty ugly and verbose in Java, but here is a version. Note, it uses StringUtils from Spring at the very end for the trivial but also ugly process of converting a String collection to a comma delimited string.
The key is to use a separate class to model the numeric ranges. Let this class know how to turn itself into a String. Then you won't have so much logic around appending to a StringBuilder.
Also, try to think in terms of collections. This always makes things clearer. The pseudo-code is something like: String becomes List<Integer> becomes List<Range> and finally becomes String.
public class Ranges {
// A class that models a range of integers
public static class Range {
private int low;
private int high;
public Range(int low, int high) {
this.low = low;
this.high = high;
}
public int getHigh() {
return high;
}
public void setHigh(int high) {
this.high = high;
}
#Override
public String toString() {
return (low == high) ? String.valueOf(low) : String.format("%d-%d", low, high);
}
}
public static void main(String[] args) {
String input = "2,3,6,7,8,10,12,14,15,16";
// Turn input string into a sorted list of integers
List<Integer> inputNumbers = new ArrayList<Integer>();
for (String num : input.split(",")) {
inputNumbers.add(Integer.parseInt(num));
}
Collections.sort(inputNumbers);
// Flatten list of integers into a (shorter) list of Ranges
Range thisRange = null; // the current range being built
List<Range> ranges = new ArrayList<Range>();
for (Integer number : inputNumbers) {
if (thisRange != null && number <= thisRange.getHigh() + 1) {
// if we are already building a range (not null) && this new number is
// the old high end of the range + 1, change the high number.
thisRange.setHigh(number);
} else {
// create a new range and add it to the list being built
thisRange = new Range(number, number);
ranges.add(thisRange);
}
}
// Join List<String> into a single String
String result = StringUtils.collectionToCommaDelimitedString(ranges);
System.out.println("result = " + result);
}
}
Here is my implementation. Hope this help.
You have to pass these values
e.g int[] a = {2,3,4,5,6,7,8,10,12, 14,15,16,18,19,21,22,26};
to the following method.
public List<String> listIntRange(int[] values)
{
List<String> intRangeList = new ArrayList<String>();
int first = 0;
int current = 0;
int prev = 0;
int count = 0;
if (values == null || values.length < 1)
return intRangeList;
first = prev = values[0];
int index = 1;
boolean range = false;
for(index = 1; index < values.length; index++)
{
current = values[index];
if(current - prev == 1)
{
range = true;
prev = current;
continue;
}
if(range == true)
{
intRangeList.add(first + "-" + prev);
}
else
{
intRangeList.add("" + first);
}
first = current;
prev = current;
range = false;
}
if(range == true)
{
intRangeList.add(first + "-" + current);
}
else
{
intRangeList.add("" + current);
}
return intRangeList;
}
Output is as follows, when print out the values from intRangeList:
2-8,10,12,14-16,18-19,21-22,26,
Please ignore last comma ','.

Categories

Resources