im trying to implement a basic form of binary search. i created an array and filled out with linear values. Now just trying to sort through it to find a number and its index.. The problem is that it is getting stuck in a constant loop and returning zero. it goes through the nested loop because it prints but is unable to find the target value. Below is the code
for (int i= 1; i < 10000 ; i++){
studentID[i] = i;
}
Students studentIDNumber = new Students();
studentIDNumber.binarySearch(studentID, 400);
public void binarySearch(int[] studentID, int targetID){
System.out.println("helloworld");
int position = -1;
int suspect;
int suspectIndex = 0;
int lastSuspectIndex = studentID.length-1;
while(position == -1)
{
assert(suspectIndex<lastSuspectIndex);
suspectIndex = ((studentID.length-1)/2);
lastSuspectIndex =suspectIndex;
suspect=studentID[suspectIndex];
System.out.println(suspect);
if(suspect == targetID){
position = suspectIndex;
System.out.println(suspectIndex +" is where the ID #"+targetID+" is sotred");
break;
}
if(suspect < targetID){
suspectIndex= suspectIndex+(suspectIndex/2);
position = -1;
}
if(suspect > targetID){
suspectIndex= suspectIndex-(suspectIndex/2);
position = -1;}
else {
System.out.println("ID not found " );
}
}
}
On this line:
suspectIndex = ((studentID.length-1)/2);
suspectIndex will be the same for every loop iteration. Initialize the variable once before the loop but not at the start of the loop itself.
Related
I'm trying to learn a bit Java with tutorials and currently I'm struggling with piece of code where I should find on which index is difference between arrays (if there is difference at all)
My code
Scanner scanner = new Scanner(System.in);
int[] arrOne = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int[] arrTwo = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int sumArrOne = 0;
int index = 0;
boolean diff = false;
for (int k : arrOne) {
if (Arrays.equals(arrOne, arrTwo)) {
sumArrOne += k;
} else {
for (int i : arrTwo) {
if (k != i) {
index = i;
diff = true;
break;
}
}
}
}
if (diff) {
System.out.println("Found difference at " + index + " index.");
} else {
System.out.println("Sum: " + sumArrOne);
}
So, if arrays are identical I'm sum array elements in arrOne. If they are not identical -> must show at which index they are not.
With this code when I input
1 2 3 4 5
1 2 4 3 5
I should get that difference is at index 2 instead I've got index 1.
I'm not quite sure why and would be glad if someone point me out where is my mistake.
I updated your code. Looks like you're misunderstanding the concept of indexes yet.
Use one common index to check with in both arrays, in my example it's simply called i:
import java.util.Arrays;
import java.util.Scanner;
public class BadArray {
static private final int INVALID_INDEX = Integer.MIN_VALUE;
public static void main(final String[] args) {
try (final Scanner scanner = new Scanner(System.in);) {
final int[] arrOne = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
final int[] arrTwo = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int sumArrOne = 0;
int diffIndex = INVALID_INDEX;
final int minLen = Math.min(arrOne.length, arrTwo.length);
for (int i = 0; i < minLen; i++) {
sumArrOne += arrOne[i];
if (arrOne[i] != arrTwo[i]) {
diffIndex = i;
break;
}
}
if (diffIndex != INVALID_INDEX) {
System.out.println("Found difference at " + diffIndex + " index.");
} else if (arrOne.length != arrTwo.length) {
System.out.println("Arrays are equal but have different length!");
} else {
System.out.println("Sum: " + sumArrOne);
}
}
}
}
I also put the scanner into a try-resource-catch to handle resource releasing properly.
Note you could also do the array lengths comparison right at the start if different array lengths play a more crucial role.
You are trying to find out which index has the first difference so you should iterate via the index rather than using a for-each loop (aka enhanced for loop). The following method should work for this.
/**
* Returns the index of the first element of the two arrays that are not the same.
* Returns -1 if both arrays have the same values in the same order.
* #param left an int[]
* #param right an int[]
* #return index of difference or -1 if none
*/
public int findIndexOfDifference(int[] left, int[] right) {
// short-circuit if we're comparing an array against itself
if (left == right) return -1;
for (int index = 0 ; index < left.length && index < right.length ; ++index) {
if (left[index] != right[index]) {
return index;
}
}
return -1;
}
In your code you compare, where the indexes are different, not the values at the indexes. Also your code has several other issues. I'll try to go through them step by step:
// compare the whole array only once, not inside a loop:
diff = !Arrays.equals(arrOne, arrTwo));
if (!diff) {
// do the summing without a loop
sumArrOne = Arrays.stream(arrOne).sum();
} else {
// find the difference
// it could be the length
index = Math.min(arrOne.length, arrTwo.length);
// or in some different values
for (int i = 0; i < index; i++) { // do a loop with counter
if (arrOne[i] != arrTwo[i]) {
index = i;
break;
}
}
}
It doesn't matter that I set index here above the loop as it's value will be overwritten anyways inside the loop, if relevant.
i new to Java, i want to know if its possible to access a array of size 0?I in a Java course and there a problem to solve where we need to calculate the sum of all element in a array,and if this sum is bigger than 100, we return true. We also need to calculate only positive number, no negative,and finally the code must work even if the array is empty. That my code here:
public static boolean biggerOrLower(){
int data[] =new int[0];
//data = new int[] {0,0,0,0,44,44,66,66,33,444,555,453,};
int iterator = 0;
boolean exced = false;
int sum = 0;
while(iterator < data.length)
{
if(iterator > 0) {
sum = sum + data[iterator];
if (sum > 100) {
exced = true;
break;
}
}
else
{
exced = false;
}
System.out.println(sum);
iterator++;
}
System.out.println(exced);
return exced;
}
}
The problem is, since iterator is = 0 , and the length of data is also 0, it never enter the while loop, but it need too, and if i change the code to while (iterator <= data.length) i got a Exception Index 0 out of bounds for length 0.
Can somebody tell why that happen and how i ca fix that?
Thank
im also a bit new to java but i think this will work
public static boolean biggerOrLower(){
int data[] =new int[0];
//data = new int[] {0,0,0,0,44,44,66,66,33,444,555,453,};
boolean exced = false;
int sum = 0;
for(int i: data){
if(i > 0){ sum += i}
}
exced = sum > 100;
System.out.println(sum);
System.out.println(exced);
return exced;
}
i don't think you need to enter the loop and i believe a for loop is much better at solving this problem
Why do you have to enter the while loop. I don't see it is necessary. You cannot access something that is empty. If you want to execute some code if the array is of size 0 you can do that with an if clause.
I am working on the project with handling a singleton class that is a list of boat. I am working on an activity that will show the longest boat. I want to try using bubble sort to sort the list by its longest boat. The app runs, but then it stop working when I press the button for showing the longest boat. Could anyone help me?
public void showLongBoat(View view)
{
//Declare references
BoatList boat_list;
TextView tv;
int i;
int x = 0;
boolean found;
int num_items;
int visit = 0;
boolean exchange_value;
int last_item;
int temp;
int a = 0;
int b;
//Set references. Access the list.
boat_list = BoatList.getInstance();
tv = (TextView) findViewById(R.id.text_main);
//Get the number of items in the list
num_items = boat_list.size();
//Find the longest boat
i = 0;
found = false;
while(!found && (i < boat_list.size()))
{
//If num_item is 0 or 1, then do not sort. Otherwise, do sorting
if(num_items > 1)
{
//Set the number of values to visit on the first pass
visit = num_items - 1;
}
do
{
//No exchange or swapping of item was made, so set the exchange to false
exchange_value = false;
//Set the index for the last item to visit
last_item = visit - 1;
for(x = 0; x <= last_item; x++)
{
if(boat_list.get(x).getLength() > boat_list.get(x).getLength() + 1)
{
//Swap the item
temp = a;
a = boat_list.get(x).getLength() + 1;
b = temp;
exchange_value = true;
}
}
visit--;
}while(exchange_value && (visit > 0)); //end sort
}
if(found)
{
boat_list.get(x).getLength();
tv.append("Longest Boat is: ");
}
else
{
Toast.makeText(ShowLongBoatActivity.this, "Error: Cannot find the longest boat successfully!",
Toast.LENGTH_SHORT).show();
}
} //end of showLongBoat
This is a infinite loop, as you don't modify found,i or the list size inside the loop:
while(!found && (i < boat_list.size()))
You don't need 3 loops in your code. If you only want the longest boat, iterate over the boats one time and take the maximum it's enough. If you want to make the sort, using a bubble sort algorithm, the biggest element will be at the end after sorting.
Trying to use Arrays.binarySearch() to search for a string in an array and return the index. However each time I call Arrays.binarySearch() I get the following exception -
Exception in thread "main" java.lang.NullPointerException
at java.util.Arrays.binarySearch0(Unknown Source)
at java.util.Arrays.binarySearch(Unknown Source)
at project.ArrayDirectory.lookupNumber(ArrayDirectory.java:97)
at project.test.main(test.java:12)
Here is my ArrayDirectory class -
public class ArrayDirectory implements Directory {
static Entry[] directory = new Entry[50];
#Override
public void addEntry(String surname, String initials, int extension) {
int n = 0;
for (int i = 0; i < directory.length; i++) { // counting number of
// entries in array
if (directory[i] != null) {
n++;
}
}
if (n == directory.length) {
Entry[] temp = new Entry[directory.length * 2]; // if array is full
// double the
// length.
for (int i = 0; i < directory.length; i++)
temp[i] = directory[i];
directory = temp;
}
int position = -1;
for (int i = 0; i < directory.length; i++) {
position = i;
if (directory[i] != null) { // sorting the array into alphabetical
// order by surname.
int y = directory[i].getSurname().compareTo(surname);
if (y > 0) {
break;
}
}
else if (directory[i] == null) {
break;
}
}
System.arraycopy(directory, position, directory, position + 1,
directory.length - position - 1);
directory[position] = new Entry(initials, surname, extension); // placing
// new
// entry
// in
// correct
// position.
}
#Override
public int lookupNumber(String surname, String initials) {
// TODO Auto-generated method stub
Entry lookup = new Entry(surname, initials);
int index = Arrays.binarySearch(directory, lookup);
return index;
}
}
Any ideas how I use binary search to find the correct index?
Thank you for you help.
edit -
I have also overridden comapreToin my Entry class -
public int compareTo(Entry other) {
return this.surname.compareTo(other.getSurname());
}
In your invocation of
int index = Arrays.binarySearch(directory,lookup);
directory seems to contain only null elements. Check that you are initializing elements correctly.
I note two things:
static Entry [] directory = new Entry [1];
First, that code allocates space for one Entry in the array. It doesn't actually instantiate an Entry. That is, directory[0] is null. Secondly, a binary-search on an array with one entry is crazy. There is only one element. It must be directory[0]. Finally, you should sort your array to do a binary search on it.
The basic concept behind a binary search is the recursion of the following steps(Note the search assumes the list or array of elements is sorted in some form and the element exists there.):
Go to the middle element of the array.
check if the searched element is equal to the element at the middle. If it is then return its index.
if not then check if the searched element is 'smaller' or 'larger' than the element in the middle.
if it is smaller then go to step 1 using only the lower/first half of the array instead of the whole.
else go to step 1 using only the upper/last half of the array instead of the whole.
As the array is continuously divided in 2 it will eventually reach the size of 1 giving the result.
Now, suppose you are looking for an integer in an int array. Here is what the code would be like:
public static int binarySearch(int number, int[] array)
{
boolean isHere = false;
Integer index =0;
for(int i=0;i<array.length;i++)
{
if(array[i] == number)
{
isHere = true;
i = array.length;
}
}
if(!isHere)
{
index = -1;
}
else
{
int arrayStart = 0;
int arrayEnd = array.length;
index = binarySearch(number, arrayStart, arrayEnd, array);
}
return index;
}
private static int binarySearch(int number, int start, int end, int[] array)
{
// this formula ensures the index number will be preserved even if
// the array is divided later.
int middle = (start+ end)/ 2;
if(array[middle] == number)
{
return middle;
}
else
{
if(number < array[middle])
{
//searches the first half of the array
return binarySearch(number, start, middle, array);
}
else
{
// searches the last half of the array
return binarySearch(number, middle, end, array);
}
}
}
You can use the compareTo() method instead of <,>, & == operators in your example. The logic should still be the same.
I'm trying to search through an array of arrays (17 rows and 26 columns) for one integer and print the index of that integer. For the sake of easy testing I've set the integer I'm searching for to 0, and all the array values are left default (0), so I should see every index printed by the time my code is finished running.
The rows are printing correctly, but an out of bounds exception is thrown when columnIncrement > 16.
Anybody know what I did wrong? Any help is greatly appreciated!
private static void search(int[][] arrayofArrays, int num) {
for(int rowIncrement = 0; rowIncrement < arrayofArrays.length; rowIncrement++) {
for (int columnIncrement = 0; columnIncrement < arrayofArrays[columnIncrement].length; columnIncrement++) {
if (arrayofArrays[rowIncrement][columnIncrement] == num) {
System.out.println("The integer you are looking for is in " + rowIncrement + "-" + columnIncrement);
}
}
}
return;
}
public static void main(String[] args) {
int[][] data = new int[17][26];
int integer = 0;
search(data, integer);
}
your for loop should be
for(int rowIncrement = 0; rowIncrement < arrayofArrays.length; rowIncrement++) {
for (int columnIncrement = 0; columnIncrement < arrayofArrays[rowIncrement].length; columnIncrement++) {
if (arrayofArrays[rowIncrement][columnIncrement] == num) {
System.out.println("The integer you are looking for is in " + rowIncrement + "-" + columnIncrement);
}
}
}
In second for loop you are checking as arrayOfArrays[columnIncrement] instead of arrayOfArrays[rowIncrement] thats what causing the problem
change arrayofArrays[columnIncrement].length to arrayofArrays[rowIncrement].length in your second for loop.
Your second for loop needs to have arrayofArrays[rowIncrement].length.
In your inner loop, you should have: columnIncrement < arrayofArrays[rowIncrement].length