label doesn't work, I tried my best - java

I tried continue & break labels in java but it throw errors.
Here is the code:
private int search(int[] seq, int key, int low, int high){
int mid = low + (high - low) / 2;
out : //label
if (key == mid) {
return mid;
}
if (key < mid) {
high = mid;
if (key != mid) {
break out;
}
}
return 1;
}

Labels are to be used with loops if you have 3 loops and you need to call break; in the innermost loop, you would then use a label to break to the outer loop because if you just call break; it will break the innermost and go to the middle loop. Your using the label wrong and you could easilly solve your problem by using either if .. if else and else statements or use the switch statement.

Labelled break works only with cycles.
And beware, they are not equivalent with goto because they transfer the control to the next statement after the break-ed cycle.
Here an example copied from the language basics tutorial - break statement on Oracle's site (I'm too lazy to be original if other good examples are available):
public static void main(String[] args) {
int[][] arrayOfInts = {
{ 32, 87, 3, 589 },
{ 12, 1076, 2000, 8 },
{ 622, 127, 77, 955 }
};
int searchfor = 12;
int i;
int j = 0;
boolean foundIt = false;
search:
for (i = 0; i < arrayOfInts.length; i++) {
for (j = 0; j < arrayOfInts[i].length;j++) {
if (arrayOfInts[i][j] == searchfor) {
foundIt = true;
break search;
}
}
}
if (foundIt) // etc
}
}
Just in case you are interested more on how to solve the binary search than how to use breaking to labels. The code below has the same performance as one that would use goto's (if they'd actually exist in java).
private static int search(int[] seq, int key, int low, int high) {
while (low <= high) {
// this is as good as low+(high-low)/2.
int mid = (low + high) >>> 1; // this is (low+high)/2
int midVal = seq[mid];
if (midVal < key) {
low = mid + 1;
}
else if (midVal > key) {
high = mid - 1;
}
else {
// why break when you can return?
return mid; // key found
}
}
// key not found. Return the 2's complement of the insert position:
// that is -(insertPosition+1)
return -(low + 1);
}

Related

Java's .sort() method breaks the while loop

Recently started learning Java and during implementing the "binary search" found out that if I call the Arrays.sort() on the array I am about to search in, it makes the loop to be infinite. Removing/commenting out the line solves the problem, but I cannot get why. My intension is to pass the sorted array to the .binarySearch() method. Tried to figure out with debugger but could not. Don't want to leave this question without the answer, can anyone, please, help?
import java.util.Arrays;
public class Main {
static class BinarySearch {
int binarySearch(int[] array, int value) {
int low = 0;
int high = array.length - 1;
while (low <= high) {
int mid = low + high / 2;
int guess = array[mid];
if (guess == value) {
return mid;
} else if (guess > value) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
}
public static void main(String[] args) {
BinarySearch bs = new BinarySearch();
int[] a = {1, 3, 4, 45, 54, 666, 2, 4};
Arrays.sort(a);
int result = bs.binarySearch(a, 45);
if (result == -1) {
System.out.println("value not found");
} else {
System.out.println("value found at position: " + result);
}
}
}
Arrays.sort doesn't really have anything to do with you ending up with an infinite loop. It's the way you calculate mid.
Should've been (low + high) / 2. You seem to have forgot to add parentheses.

Searching a sorted list with two different algorithms to find if there exists an index i such that X[i]=i

Note that the list will never contain duplicates.
The list is loaded from a text file and is the following 1,2,3,4,5,6,7,8,9.
My first choice since the list is sorted was a linear search and worked fine. Then I tried to use binary search but it does not work correctly.
Here is the code:
public boolean binarySearch() {
int i=0;
int size = list.size() - 1;
while (i <= size) {
int mid = (i + size) / 2;
if (mid == list.get(mid)) {
return true;
}
if (mid < list.get(mid)) {
size = mid - 1;
} else {
i = mid + 1;
}
}
return false;
}
Here is an O(log n) solution.
public static void main(String args[]) {
System.out.println(binarySearch(new int[] {-100, -50, -30, 3, 500, 800}));
System.out.println(binarySearch(new int[] {-100, -50, -30, 42, 500, 800}));
System.out.println(binarySearch(new int[] {-8, 1, 2, 3, 4, 100, 200, 300, 500, 700, 9000}));
}
// Searches for a solution to x[i]=i, returning -1 if no solutions exist.
// The algorithm only works if the array is in ascending order and has no repeats.
// If there is more than one solution there is no guarantee which will
// be returned. Worst case time complexity O(log n) where n is length of array.
public static int binarySearch(int[] x) {
if (x == null || x.length == 0)
return -1;
int low = 0;
if (x[low] == low)
return 0;
else if (x[low] > low)
return -1;
int high = x.length - 1;
if (x[high] == high)
return high;
else if (x[high] < high)
return -1;
while (high - low >= 2) {
int mid = (high + low) / 2;
if (x[mid] == mid)
return mid;
else if (x[mid] > mid)
high = mid;
else low = mid;
}
return -1;
}
public class NewMain1 {
public static void main(String[] args) {
int [] x = {1,2,3,4,5,6};
int value = 7;
boolean check = binarySearch(x,value);
System.out.println(check);
}
public static boolean binarySearch(int [] list , int value) {
int i=0;
int size = list.length - 1;
while (i <= size) {
int mid = (i + size) / 2;
if (value == list[mid]) {
return true;
}
if (value < list[mid]) {
size = mid - 1;
} else {
i = mid + 1;
}
}
return false;
}
I think this could help you

How to use recursion in creating a binary search algorithm

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;
}
}

Implementing a binary insertion sort using binary search in Java

I'm having trouble combining these two algorithms together. I've been asked to modify Binary Search to return the index that an element should be inserted into an array. I've been then asked to implement a Binary Insertion Sort that uses my Binary Search to sort an array of randomly generated ints.
My Binary Search works the way it's supposed to, returning the correct index whenever I test it alone. I wrote out Binary Insertion Sort to get a feel for how it works, and got that to work as well. As soon as I combine the two together, it breaks. I know I'm implementing them incorrectly together, but I'm not sure where my problem lays.
Here's what I've got:
public class Assignment3
{
public static void main(String[] args)
{
int[] binary = { 1, 7, 4, 9, 10, 2, 6, 12, 3, 8, 5 };
ModifiedBinaryInsertionSort(binary);
}
static int ModifiedBinarySearch(int[] theArray, int theElement)
{
int leftIndex = 0;
int rightIndex = theArray.length - 1;
int middleIndex = 0;
while(leftIndex <= rightIndex)
{
middleIndex = (leftIndex + rightIndex) / 2;
if (theElement == theArray[middleIndex])
return middleIndex;
else if (theElement < theArray[middleIndex])
rightIndex = middleIndex - 1;
else
leftIndex = middleIndex + 1;
}
return middleIndex - 1;
}
static void ModifiedBinaryInsertionSort(int[] theArray)
{
int i = 0;
int[] returnArray = new int[theArray.length + 1];
for(i = 0; i < theArray.length; i++)
{
returnArray[ModifiedBinarySearch(theArray, theArray[i])] = theArray[i];
}
for(i = 0; i < theArray.length; i++)
{
System.out.print(returnArray[i] + " ");
}
}
}
The return value I get for this when I run it is 1 0 0 0 0 2 0 0 3 5 12. Any suggestions?
UPDATE: updated ModifiedBinaryInsertionSort
static void ModifiedBinaryInsertionSort(int[] theArray)
{
int index = 0;
int element = 0;
int[] returnArray = new int[theArray.length];
for (int i = 1; i < theArray.lenght - 1; i++)
{
element = theArray[i];
index = ModifiedBinarySearch(theArray, 0, i, element);
returnArray[i] = element;
while (index >= 0 && theArray[index] > element)
{
theArray[index + 1] = theArray[index];
index = index - 1;
}
returnArray[index + 1] = element;
}
}
Here is my method to sort an array of integers using binary search.
It modifies the array that is passed as argument.
public static void binaryInsertionSort(int[] a) {
if (a.length < 2)
return;
for (int i = 1; i < a.length; i++) {
int lowIndex = 0;
int highIndex = i;
int b = a[i];
//while loop for binary search
while(lowIndex < highIndex) {
int middle = lowIndex + (highIndex - lowIndex)/2; //avoid int overflow
if (b >= a[middle]) {
lowIndex = middle+1;
}
else {
highIndex = middle;
}
}
//replace elements of array
System.arraycopy(a, lowIndex, a, lowIndex+1, i-lowIndex);
a[lowIndex] = b;
}
}
How an insertion sort works is, it creates a new empty array B and, for each element in the unsorted array A, it binary searches into the section of B that has been built so far (From left to right), shifts all elements to the right of the location in B it choose one right and inserts the element in. So you are building up an at-all-times sorted array in B until it is the full size of B and contains everything in A.
Two things:
One, the binary search should be able to take an int startOfArray and an int endOfArray, and it will only binary search between those two points. This allows you to make it consider only the part of array B that is actually the sorted array.
Two, before inserting, you must move all elements one to the right before inserting into the gap you've made.
I realize this is old, but the answer to the question is that, perhaps a little unintuitively, "Middleindex - 1" will not be your insertion index in all cases.
If you run through a few cases on paper the problem should become apparent.
I have an extension method that solves this problem. To apply it to your situation, you would iterate through the existing list, inserting into an empty starting list.
public static void BinaryInsert<TItem, TKey>(this IList<TItem> list, TItem item, Func<TItem, TKey> sortfFunc)
where TKey : IComparable
{
if (list == null)
throw new ArgumentNullException("list");
int min = 0;
int max = list.Count - 1;
int index = 0;
TKey insertKey = sortfFunc(item);
while (min <= max)
{
index = (max + min) >> 1;
TItem value = list[index];
TKey compKey = sortfFunc(value);
int result = compKey.CompareTo(insertKey);
if (result == 0)
break;
if (result > 0)
max = index - 1;
else
min = index + 1;
}
if (index <= 0)
index = 0;
else if (index >= list.Count)
index = list.Count;
else
if (sortfFunc(list[index]).CompareTo(insertKey) < 0)
++index;
list.Insert(index, item);
}
Dude, I think you have some serious problem with your code. Unfortunately, you are missing the fruit (logic) of this algorithm. Your divine goal here is to get the index first, insertion is a cake walk, but index needs some sweat. Please don't see this algorithm unless you gave your best and desperate for it. Never give up, you already know the logic, your goal is to find it in you. Please let me know for any mistakes, discrepancies etc. Happy coding!!
public class Insertion {
private int[] a;
int n;
int c;
public Insertion()
{
a = new int[10];
n=0;
}
int find(int key)
{
int lowerbound = 0;
int upperbound = n-1;
while(true)
{
c = (lowerbound + upperbound)/2;
if(n==0)
return 0;
if(lowerbound>=upperbound)
{
if(a[c]<key)
return c++;
else
return c;
}
if(a[c]>key && a[c-1]<key)
return c;
else if (a[c]<key && a[c+1]>key)
return c++;
else
{
if(a[c]>key)
upperbound = c-1;
else
lowerbound = c+1;
}
}
}
void insert(int key)
{
find(key);
for(int k=n;k>c;k--)
{
a[k]=a[k-1];
}
a[c]=key;
n++;
}
void display()
{
for(int i=0;i<10;i++)
{
System.out.println(a[i]);
}
}
public static void main(String[] args)
{
Insertion i=new Insertion();
i.insert(56);
i.insert(1);
i.insert(78);
i.insert(3);
i.insert(4);
i.insert(200);
i.insert(6);
i.insert(7);
i.insert(1000);
i.insert(9);
i.display();
}
}

Java - My sort is not working

I have created the following class to sort an array of strings.
public class StringSort {
private String[] hotelNames;
private int arrayLength;
public void sortHotel(String[] hotelArray) {
if (hotelArray.length <= 1) {
return;
}
this.hotelNames = hotelArray;
arrayLength = hotelArray.length;
quicksort(0, arrayLength - 1);
}
private void quicksort(int low, int high) {
int i = low, j = high;
String first = hotelNames[low];
String last = hotelNames[high];
String pivot = hotelNames[low + (high - low) / 2];
while( (first.compareTo(last)) < 0 ) { // first is less than last
while( (hotelNames[i].compareTo(pivot)) < 0 ) { // ith element is < pivot
i++;
}
while( (hotelNames[j].compareTo(pivot)) > 0) { // jth element is > pivot
j--;
}
if ( ( hotelNames[i].compareTo( hotelNames[j] )) <= 0 ) {
swap(i, j);
i++;
j--;
}
//recursive calls
if (low < j) {
quicksort(low, j);
}
if (i < high) {
quicksort(i, high);
}
}
}
private void swap(int i, int j) {
String temp = hotelNames[i];
hotelNames[i] = hotelNames[j];
hotelNames[j] = temp;
}
}
However in my main class (a class to test StringSort), when I do:
StringSort str = new StringSort();
String[] hotel1 = {"zzzz", "wwww", "dddd", "bbbbb", "bbbba", "aaaf", "aaag", "zzz"};
str.sortHotel(hotel1);
And then I have another method that prints out the array. However when it prints out, it outputs the hotel1 array as it is, unchanged. There is no 'sorting' happening, I'm not sure where I've gone wrong.
There are several problems in your implementation of quicksort:
First/last comparison. This code will made your quicksort not do anything as long as first element is less than the last element, regardless of any other order.
while( (first.compareTo(last)) < 0 ) { // first is less than last
Check before swap. This line is unnecessary:
if ( ( hotelNames[i].compareTo( hotelNames[j] )) <= 0 ) {
What you really want to do is see if the i is still less than j and bail out of the loop then. If not, then swap. After you finished with the partitioning loop, then make the recursive call, as long as there are more than two elements in each subarray.

Categories

Resources