The goal of this project is to create a class search. I will need methods of binary search and linear search. For each method you are going to ask the user for a key, then search for this key in an array of numbers (you can assume the numbers in the array). If you found the key return its location, otherwise returns -1. Test these methods by creating an object from the Search class (in the main method) and calling the linear and the binary methods.
Below I have created the code and I am trying to create my main so I can test the linear and binary methods but it is not working. It could be because I'm testing like three different classes in the same main, but I am not sure I formatted them in the right way and that's the reason why I am getting errors. I need help, please.
My Search class.
`
public class Search {
public static int linearsearch(int arr2[], int x2) {
int N = arr2.length;
for (int i = 0; i < N; i++) {
if (arr2[i] == x2)
return i;
}
return -1;
}
public int binarySearch(int arr3[], int l, int r, int x) {
if (r >= l) {
int mid = l + (r-1)/2;
if (arr3[mid] ==x)
return mid;
if(arr3[mid] > x)
return binarySearch(arr3, l, mid -1, x);
return binarySearch(arr3, mid + 1, r, x);
}
return -1;
}
}
My Main class
public class MainTester {
public static void main(String args[]) {
//sorting tester
Sorting obj = new Sorting();
int arr[] = {9,5,4,1,6,10,3,2,7,8};
obj.bubbleSort(arr);
System.out.println("Sorted array:");
obj.printArray(arr);
//binary search tester
int arr3[] = {2,3,5,4,30};
int n = arr3.length;
int x = 10;
int result = binarySearch(arr3, 0, n-1, x);
if (result == -1)
System.out.println("Element not present");
else System.out.println("Element found " + result);
//linear search tester
int arr2[] = {2,3,4,10,30};
int x2 = 10;
int result2 = linearsearch(arr2, x2);
if (result2 == -1)
System.out.print("Element is not present in array.");
else
System.out.print("Element is present " +result2);
}
private static int binarySearch(int[] arr3, int l, int r, int x) {
// TODO Auto-generated method stub
return -1;
}
private static int linearsearch(int[] arr2, int x) {
// TODO Auto-generated method stub
return -1;
}
}
I was expecting this code to test all my methods in the main so I can print the result of my binary and linear search
Here is a working version of your code.
There was still some mistakes. See comments in code below.
Class 'Search'
//Don't mix static and non static method
public class Search {
//linearsearch replaced by linearSearch: use camel case in your class and method names
//Try to use variable names that will help to understand your code.
//Here 'x' has been replaced by 'numberToFind'
public int linearSearch(int arr[], int numberToFind) {
int n = arr.length;//N replaced by n: use Java coding convention
for (int i = 0; i < n; i++) {
if (arr[i] == numberToFind)
return i;
}
return -1;
}
public int binarySearch(int arr[], int l, int r, int numberToFind) {
if (r >= l) {
// There was an error at line below when calculating the 'mid' number
// int mid = l + (r - 1) / 2;
int mid = (l + r) / 2;
if (arr[mid] == numberToFind)
return mid;
if (arr[mid] > numberToFind)
return binarySearch(arr, l, mid - 1, numberToFind);
return binarySearch(arr, mid + 1, r, numberToFind);
}
return -1;
}
}
Class 'MainTester'
Try to avoid repetitive code.
If you have some, extract it to another method and call that method.
public class MainTester {
private Search search;
public MainTester() {
super();
search = new Search();
}
public void testLinearSearch(int[] numberArray, int numberToFind) {
int result = search.linearSearch(numberArray, numberToFind);
printResult("Linear search: ", numberToFind, result);
}
public void testBinarySearch(int[] arr, int numberToFind) {
int result = search.binarySearch(arr, 0, arr.length - 1, numberToFind);
printResult("Binary search: ", numberToFind, result);
}
private void printResult(String searchType, int searchNumber, int arrayIndex) {
if (arrayIndex == -1)
System.out.println(searchType + "Element " + searchNumber + " is not present in array.");
else
System.out.println(searchType + "Element " + searchNumber + " is present at index " + arrayIndex);
}
public static void main(String args[]) {
MainTester tester = new MainTester();
// Try to find a number using linear search
int numbertoFind = 10;
int[] arr2 = { 2, 3, 4, 10, 30 };
tester.testLinearSearch(arr2, 10);
// Try to find a number using binary search with an unsorted array: will not
// work
numbertoFind = 4;
int[] unsortedArray = { 2, 3, 5, 4, 30 };
tester.testBinarySearch(unsortedArray, numbertoFind);
// Try to find a number using binary search with an sorted array: works
int sortedArray[] = { 2, 3, 4, 5, 30 };
tester.testBinarySearch(sortedArray, numbertoFind);
}
}
Hope it helps.
Related
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);
}
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 find range(max - min) of an array using recursion.
Since, there can be only one return value, I am kind of confused how to go about this problem.
What I have done so far is to find maximum and minimum recursively and then use this in range function to find the range. I was wondering if it was possible to do everything in just range function somehow recursively.
public static int max(int[] array, int N) {
int maximum;
if (N >= array.length) {
maximum = Integer.MIN_VALUE;
} else {
maximum = max(array, N + 1);
if (array[N] > maximum) {
maximum = array[N];
}
}
return maximum;
}
public static int min(int[] array, int N) {
int minimum;
if (N >= array.length) {
minimum = Integer.MAX_VALUE;
} else {
minimum = min(array, N + 1);
if (array[N] < minimum) {
minimum = array[N];
}
}
return minimum;
}
public static int range(int [] array)
{
int max1 = max(array , 0);
System.out.println(max1);
int min1 = min(array , 0);
System.out.println(min1);
int range = max1 - min1;
return range;
}
If recursion really is a requirement, and you just need the range, then this should do it:
public static int range(int [] array, int index, int min, int max)
{
if (index == array.length) {
if (index == 0)
return 0;
else
return max - min;
}
else {
int value = array[index];
return range(array, index + 1, Math.min(value, min), Math.max(value, max));
}
}
public static int range(int [] array)
{
return range(array, 0, Integer.MAX_VALUE, Integer.MIN_VALUE);
}
Your algorithm seems waaaay too complicated for what you're trying to do.
It's not clear if using recursion is a requirement. If it is not, what about this?
public int range (int[] array) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int elem : array) {
if (elem < min) min = elem;
if (elem > max) max = elem;
}
return (max - min);
}
On mobile so I cannot test any code, but it should work.
EDIT: Ok sorry, re-reading your question I see you just want to know how to do it using recursion. Maybe you'd like to make that clear in the title itself ;-)
You could provide a int[] with min (index 0) and max (index 1) within the method and do all in the same method.
public class Test {
#org.junit.Test
public void test() {
int[] array = new int[] { -5,2,4,6,-10,44};
int[] minmax = new int[ 2 ];
minmax( array, minmax, 0 );
assertEquals( "[-10, 44]", Arrays.toString( minmax ) );
}
public static void minmax(int[] array, int[] minmax, int N) {
if (N >= array.length) {
return;
} else {
minmax(array, minmax, N + 1);
if (array[N] < minmax[0]) {
minmax[0] = array[N];
}
if (array[N] > minmax[1]) {
minmax[1] = array[N];
}
}
}
}
You could for example return an array (0 would have min and 1 have max) that way you can return both values.
A nicer way would be to pass a callback function to you method and call that once done.
findMinMax(array, (min, max) -> { System.out.println(min + " " + max);});
private void findMinMax(int[] array, BiFunction<Integer, Integer, Void> callback) {
//Do things
callback.apply(min, max);
}
This problem doesn't have any improvement from recursion, since it is a iterative problem that - instead - can result in performance issue due to the growing of stack size, in particular for big arrays.
Anyway, a more classical example in java 7 can be the following, where you can use a minimal "Couple" class to store min/max values
public class MaxMinRecurse {
void evalMaxMinInInterval(Couple maxmin, int pos, int[] values) {
if (pos >= values.length)
return;
int x = values[pos];
if (x < maxmin.min) {
maxmin.min = x;
} else if (x > maxmin.max) {
maxmin.max = x;
}
evalMaxMinInInterval(maxmin, pos + 1, values);
}
public static void main(String[] args) {
MaxMinRecurse mmr = new MaxMinRecurse();
int[] values = { 1, 5, 3, 4, 7, 3, 4, 13 };
Couple result = mmr.new Couple();
mmr.evalMaxMinInInterval(result, 0, values);
System.out.println("Max: " + result.max + ", Min:" + result.min);
}
class Couple {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
}
}
I am trying to solve this CodeChef problem:
There are N coins kept on the table, numbered from 0 to N - 1. Initially, each coin is kept tails up.
You have to perform two types of operations:
Flip all coins numbered between A and B inclusive. This is represented by the command "0 A B"
Answer how many coins numbered between A and B inclusive are heads up. This is represented by the command "1 A B".
Input: The first line contains two integers, N and Q. Each of the next Q lines are either of the form "0 A B" or "1 A B" as mentioned above.
Output: Output 1 line for each of the queries of the form "1 A B" containing the required answer for the corresponding query.
What I have used is a segment tree. So that every time user enter a query of type 1 A B the output is the sum at that interval [A,B]. However I am getting a Time Limit Exceeded error. I believe the error is due to the update step 0 A B. After updating the elements in the array I reconstruct the tree. The code is given below. Can someone help me with a faster way to update?
BTW - I am getting the desired output for the sample input.
public class SegmentTree
{
private int[] tree;
private int maxsize;
private int height;
private static int elems[];
private final int STARTINDEX = 0;
private final int ENDINDEX;
private final int ROOT = 0;
public SegmentTree(int size)
{
height = (int)(Math.ceil(Math.log(size) / Math.log(2)));
maxsize = 2 * (int) Math.pow(2, height) - 1;
tree = new int[maxsize];
ENDINDEX = size - 1;
}
private int leftchild(int pos)
{
return 2 * pos + 1;
}
private int rightchild(int pos)
{
return 2 * pos + 2;
}
private int mid(int start, int end)
{
return (start + (end - start) / 2);
}
private int getSumUtil(int startIndex, int endIndex, int queryStart, int queryEnd, int current)
{
if (queryStart <= startIndex && queryEnd >= endIndex)
{
return tree[current];
}
if (endIndex < queryStart || startIndex > queryEnd)
{
return 0;
}
int mid = mid(startIndex, endIndex);
return getSumUtil(startIndex, mid, queryStart, queryEnd, leftchild(current))
+ getSumUtil( mid + 1, endIndex, queryStart, queryEnd, rightchild(current));
}
public int getSum(int queryStart, int queryEnd)
{
if(queryStart < 0 || queryEnd > tree.length)
{
return -1;
}
return getSumUtil(STARTINDEX, ENDINDEX, queryStart, queryEnd, ROOT);
}
private int constructSegmentTreeUtil(int startIndex, int endIndex, int current)
{
if (startIndex == endIndex)
{
tree[current] = elems[startIndex];
return tree[current];
}
int mid = mid(startIndex, endIndex);
tree[current] = constructSegmentTreeUtil(startIndex, mid, leftchild(current))
+ constructSegmentTreeUtil(mid + 1, endIndex, rightchild(current));
return tree[current];
}
public void constructSegmentTree()
{
constructSegmentTreeUtil(STARTINDEX, ENDINDEX, ROOT);
}
public static void main(String[]args) throws IOException
{
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer str = new StringTokenizer(buf.readLine());
int n = Integer.parseInt(str.nextToken());
int q = Integer.parseInt(str.nextToken());
SegmentTree segmentTree = new SegmentTree(n);
int elements[] = new int[n];
for(int i = 0; i < n; i++) {
elements[i] = 0;
}
elems = elements;
segmentTree.constructSegmentTree();
while (q-- > 0) {
str = new StringTokenizer(buf.readLine());
int x = Integer.parseInt(str.nextToken());
int a = Integer.parseInt(str.nextToken());
int b = Integer.parseInt(str.nextToken());
if(x == 0) {
for(int j = a; j <= b; j++)
{
elems[j] = elems[j]^1;
}
segmentTree.constructSegmentTree();
}
else {
int num = segmentTree.getSum(a, b);
System.out.println(num);
}
}
}
}
EDIT:
According to GeeksForGeeks, tree construction costs O(n) and the update method is O(log n). So here are the new methods for update:
private void updateTreeUtil(int startIndex, int endIndex, int updatePos, int update, int current)
{
if ( updatePos < startIndex || updatePos > endIndex)
{
return;
}
tree[current] = tree[current] + update;
if (startIndex != endIndex)
{
int mid = mid(startIndex, endIndex);
updateTreeUtil(startIndex, mid, updatePos, update, leftchild(current));
updateTreeUtil(mid+1, endIndex, updatePos, update, rightchild(current));
}
}
public void update(int update, int updatePos)
{
int updatediff = update - elems[updatePos];
elems[updatePos] = update;
updateTreeUtil(STARTINDEX, ENDINDEX, updatePos, updatediff, ROOT);
}
And now the if loop in main method modified to this:
if(x == 0) {
for(int j = a; j <= b; j++)
{
segmentTree.update(elems[j]^1, j);
}
}
But still getting TLE error.
In the tutorial of GeeksForGeeks, their running time of update is O(log n), in case of updating a single element. However, when doing update for an interval, you have to use Lazy Propagation to ensure O(log n) update time, which is basically only update nodes which are visited, and hence ensure the sum of visited nodes are correct. You may search for many good tutorial on Lazy Propagation, for example:
http://se7so.blogspot.hk/2012/12/segment-trees-and-lazy-propagation.html
Wish that helps.
I was asked to sort and search an array. The sorting the array was simple and my code worked but then whenever I try to call the binary search method it works for the first element in the array but gives me "-1" as a result
My full code is as follows:
public static void main(String[] args) {
int[] array = new int[5];
array[0] = 50;
array[1] = 40;
array[2] = 10;
array[3] = 20;
array[4] = 100;
sort(array, (array.length - 1));
for (int x = 0; x < array.length; x++) {
System.out.println(" " + array[x]);
}
System.out.println("");
System.out.println("Binary search (R): " + rBsearch(array, 0, (array.length), 20));
}
public static void sort(int[] a, int last) {
if (last > 0) {
int max = findMax(a, last);
swap(a, last, max);
sort(a, last - 1);
}
}
public static int rBsearch(int[] L, int low, int high, int k) {
int mid = (low + high) / 2;
if (low > high) {
return -1;
} else if (L[mid] == k) {
return mid;
} else if (L[mid] < k) {
return rBsearch(L, k, mid + 1, high);
} else {
return rBsearch(L, k, low, mid - 1);
}
}
public static int findMax(int[] arr, int last) {
int max = 0;
for (int i = 0; i <= last; i++) {
if (arr[i] > arr[max]) {
max = i;
}
}
return max;
}
public static void swap(int[] arr, int last, int max) {
int temp = arr[last];
arr[last] = arr[max];
arr[max] = temp;
}
You goofed up the binary search intervals
public static int rBsearch(int[] L, int low, int high, int k) {
int mid = (low + high) / 2;
if (low > high) {
return -1;
} else if (L[mid] == k) {
return L[mid];
} else if (L[mid] < k) {
return rBsearch(L, mid + 1, high, k);
} else {
return rBsearch(L, low, mid - 1, k);
}
}
You did a mistake in calling the rBsearch method in the following lines
Instead of
else if (L[mid] < k) {
return rBsearch(L, k, mid + 1, high);
} else {
return rBsearch(L, k, low, mid - 1);
}
You should use
else if (L[mid] < k) {
return rBsearch(L, mid + 1, high,k); //the order of the parameters
} else {
return rBsearch(L, low, mid - 1,k);
}
Easiest way is:
Convert you array to list: Arrays.asList(array)
For sort: Collections#sort
For search: Collections#binarySearch
See this
Take Array From User
Sort Array using Build-in Function of Java...
then Search Element using Binary Search....
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Scanner;
class BinarySearch
{
public static void main(String args[])
{
int array[];
Scanner input = new Scanner(System.in);
System.out.println("Enter number of elements:");
int Size_Of_Array = input.nextInt();
array = new int[Size_Of_Array];
System.out.println("Enter " + Size_Of_Array + " integers");
for (int counter = 0; counter < Size_Of_Array; counter++)
array[counter] = input.nextInt();
Arrays.sort(array);
System.out.println("Sorting Array is :-");
for (int counter = 0; counter < Size_Of_Array; counter++)
System.out.println(array[counter]);
System.out.println("Enter the search value:");
int Searching_item = input.nextInt();
int First_Index=0;
int Last_Index=Size_Of_Array-1;
int Middle_Index=(First_Index+Last_Index)/2;
while(First_Index <= Last_Index)
{
if(array[Middle_Index] < Searching_item)
{
First_Index=Middle_Index+1;
}
else if ( array[Middle_Index] == Searching_item )
{
System.out.println(Searching_item + " found at location " + (Middle_Index + 1) + ".");
break;
}
else
{
Last_Index = Middle_Index - 1;
}
Middle_Index = (First_Index + Last_Index)/2;
if ( First_Index > Last_Index )
{
System.out.println(Searching_item + " is not found.\n");
}
}
}
}
Result of BinarySearch