Binary search on an array giving wrong value - java

I'm doing a binary search on an array. But somethings to be off. It returns -1 as if the target is not being found but it is in the array.
ex: when I put the key at 555 it returns the correct index but when I try with the example below with 8 it returns -1..
public class bSearch {
public static void main(String[] args) {
int[] nums = {9,5,2,5,7,8,3,22,555};
int key = 8;
System.out.println(searchForNum(nums,0,nums.length-1,key));
}
private static int searchForNum(int[] arr,int first, int last, final int target) {
int middle= (first+last)/2;
if(last < first) {
return -1;
}
if(arr[middle]== target)
return middle;
else if(target < arr[middle]) {
return searchForNum(arr,first,middle-1,target);
} else {
return searchForNum(arr,middle+1,last,target);
}
}
}

The reason why binary search works is that the search interval is ordered. You are passing an unordered interval, which leads to search errors.
Call Arrays.sort on your data array before searching:
int[] nums = {9,5,2,5,7,8,3,22,555};
Arrays.sort(nums);

You can not do binary search without sorting the list/array that you want to search on it
please read this for more info binary-search.
you need to modified your main method to be
public static void main(String[] args) {
int[] nums = {9,5,2,5,7,8,3,22,555};
int key = 8;
Arrays.sort(nums); // sort the array
System.out.println(searchForNum(nums,0,nums.length-1,key));
}

Related

Function not printing the return value

public class App {
public static int start;
public static int end;
public static int search(int nums[],int target) {
System.out.println("entered search");
start=0;
end=nums.length-1;
int max=maxSearch(nums);
System.out.println("reentered search");
if(target>=nums[start]&&target<=nums[max]) {
end=max;
} else if(target>=nums[max+1]&&target<=nums[end]) {
start=max+1;
}
return (binarysearch(nums,target));
}
public static int binarysearch(int nums[],int target) {
int mid=start+(end-start)/2;
System.out.println("entered binarysearch");
while(start<end) {
if(target==nums[mid])
return mid;
if(target>nums[mid])
start=mid+1;
if(target<nums[mid])
end=mid-1;
}
return end;
}
public static int maxSearch(int nums[]) {
start=0;
end=nums.length-1;
System.out.println("entered maxSearch");
while(start<end) {
int mid=start+(end-start)/2;
if(nums[mid+1]<nums[mid])
return mid;
if(nums[mid]>nums[start])
start=mid+1;
if(nums[mid]<nums[start])
end=mid-1;
}
return end;
}
public static void main(String args[]) {
int nums[]={4,5,6,7,0,1,2};
int target=7;
System.out.println(search(nums, target));
}
}
In this, I am trying to get the index of the target. The array was an originally sorted array in ascending order. It is now rotated around an index. My programme is not printing any value for target 6 and 7 . However for the rest of the numbers, it is working alright and is giving accurate value. For example, for 4, it giving index 0 after printing the lines telling flow of control but for 6 and 7, it doesn't print any index. Can you point out what is wrong here? I want to have logn time complexity.
I was first finding the maximum number in the array(ma search) , because the left part and right part of the array is sorted since a sorted array is rotated around an index originally like [0,1,2,4,5,6,7] is rotated around index 3. Then, I checked that in which part left or right, can my target be present(Search) and at last I performed a binary search on that part(binary search).

Keep multiplying found values in an array error with recursion

I struggle with this coding "challenge".
I need to look for the original value in nums. If its there, multiply by two
and redo the whole thing.
Return the value if there is no more same value.
It works on a lot of test cases but I get a weird error with this set while debugging.
After I iterate the array and was ready to return the right value, instead of returning the 16, it calls the findFinalValue again and iterates itself from 16 down again to 4.
public class Main {
public static void main(String[] args) {
Solution s = new Solution();
int[] nums = {8,19,4,2,15,3};
System.out.println(s.findFinalValue(nums, 2));
}
}
class Solution {
public int findFinalValue(int[] nums, int original) {
for(int n: nums){
if(n == original){
original*=2;
findFinalValue(nums, original);
}
}
return original;
}
}
It is not iterating from 16 to 4, it is how recursion works. You need to pass the result back or store it in a global variable. Once the dead-end is achieved in recursion it backtracks and comes back to its original state.
Solution
class Solution {
public int findFinalValue(int[] nums, int original) {
int isPresent = false;
for(int n: nums){
if(n == original){
isPresent = true;
break;
}
}
if(isPresent) {
original = findFinalValue(nums, original*2);
}
return original;
}
}
Frankly speaking, you can optimize it by sorting the array at first and then using binary search for finding elements, in addition, the array passed in the next state can be reduced till the index has read. Because original has become twice
I wouldn't use recursion, but since I think you're asking about a recursive solution, I would do it like this:
public int findFinalValue(int[] nums, int original) {
return IntStream.of(nums).anyMatch(n -> n == original)
? findFinalValue(nums, 2 * original)
: original;
}
Guessing that your problem is that your have not implemented recursion properly:
class Solution {
public int findFinalValue(int[] nums, int original) {
int found = original;
for(int n: nums){
if(n == original){
found = findFinalValue(nums, found * 2);
}
}
return found;
}
}

How to make generic Counting Sort Method?

Okay I am a pretty beginner java coder, and I am doing an assignment where I am stuck. I need to create a generic method (sort) that sorts a Type array according to frequency, basically, I am taking the CountingSort Algorithm and making it a generic method. This is where I am lost. I can't seem to figure out how to do this.
Here is a link to my instructions,
https://classes.cs.siue.edu/pluginfile.php/7068/mod_assign/intro/150mp08.pdf
Code:
Driver Class
package mp08;
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Lists array = new Lists();
array.populateLists();
System.out.println("Original Int List: \n");
array.sort(Lists.intList);
System.out.println("Sorted Int List: \n");
}
}
Lists Class
package mp08;
import java.util.Arrays;
import java.util.Random;
public class Lists {
public static Integer[] intList;
public static Integer[] sortedintList;
public static Integer[] frequency;
public static Character[] charList;
public static Character[] sortedcharList;
public static int MAX_SIZE = 101;
public static int lengthInt;
public static int lengthChar;
public Lists(){
this.intList = new Integer[MAX_SIZE];
this.sortedintList = new Integer[MAX_SIZE];
this.charList = new Character[MAX_SIZE];
this.sortedcharList = new Character[MAX_SIZE];
this.frequency = new Integer[MAX_SIZE];
this.lengthInt = 0;
this.lengthChar = 0;
}
//Makes random integer for populated lists method.
public int randomInt(int min, int max){
Random rand = new Random();
int randomNum = rand.nextInt((max-min)+1)+min;
return randomNum;
}
//Makes random character for populated lists method.
public char randomChar(){
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int N = alphabet.length();
Random rand = new Random();
char randomLet = alphabet.charAt(rand.nextInt(N));
return randomLet;
}
//Populates intList and charList with random values.
public void populateLists(){
for (int i = 0; i < MAX_SIZE; i++) {
intList[i] = randomInt(1,100);
lengthInt++;
}
for (int i = 0; i < MAX_SIZE; i++) {
charList[i] = randomChar();
lengthChar++;
}
}
//Returns sorted array
public Integer[] sorted(){
return intList;
}
public static <T> void sort(T[] array) {
// array to be sorted in, this array is necessary
// when we sort object datatypes, if we don't,
// we can sort directly into the input array
Integer[] aux = new Integer[array.length];
// find the smallest and the largest value
int min = 1;
int max = 101;
// init array of frequencies
int[] counts = new int[max - min + 1];
// init the frequencies
for (int i = 0; i < array.length; i++) {
counts[array[i] - min]++;
}
// recalculate the array - create the array of occurence
counts[0]--;
for (int i = 1; i < counts.length; i++) {
counts[i] = counts[i] + counts[i-1];
}
/*
Sort the array right to the left
1) Look up in the array of occurences the last occurence of the given value
2) Place it into the sorted array
3) Decrement the index of the last occurence of the given value
4) Continue with the previous value of the input array (goto set1),
terminate if all values were already sorted
*/
for (int i = array.length - 1; i >= 0; i--) {
aux[counts[array[i] - min]--] = array[i];
}
}
public static void main(String[] args) {
Integer [] unsorted = {5,3,0,2,4,1,0,5,2,3,1,4};
System.out.println("Before: " + Arrays.toString(unsorted));
Integer [] sorted = sort(unsorted);
System.out.println("After: " + Arrays.toString(sorted));
}
}
I obviously have not finished my driver class yet and I would appreciate any help I can get!
There's no generic way for any Comparable type to get its ordinal number. Sometimes such numbers do not exist at all (for example, String is Comparable, but you cannot map any String to the integer number). I can propose two solutions.
First one is to store counts not in the array, but in TreeMap instead creating new entries on demand (using Java-8 syntax for brevity):
public static <T extends Comparable<T>> void sort(T[] array) {
Map<T, Integer> counts = new TreeMap<>();
for(T t : array) {
counts.merge(t, 1, Integer::sum);
}
int i=0;
for(Map.Entry<T, Integer> entry : counts.entrySet()) {
for(int j=0; j<entry.getValue(); j++)
array[i++] = entry.getKey();
}
}
public static void main(String[] args) {
Integer[] data = { 5, 3, 0, 2, 4, 1, 0, 5, 2, 3, 1, 4 };
System.out.println("Before: " + Arrays.toString(data));
sort(data);
System.out.println("After: " + Arrays.toString(data));
Character[] chars = { 'A', 'Z', 'B', 'D', 'F' };
System.out.println("Before: " + Arrays.toString(chars));
sort(chars);
System.out.println("After: " + Arrays.toString(chars));
}
Such solution looks clean, but probably not very optimal (though its advantage is that it does not care whether all numbers are from 1 to 100 or not).
Another possible solution is to create some additional interface which defines ordering for given type:
public interface Ordering<T> {
int toOrdinal(T obj);
T toObject(int ordinal);
}
public class IntegerOrdering implements Ordering<Integer> {
#Override
public int toOrdinal(Integer obj) {
return obj;
}
#Override
public Integer toObject(int ordinal) {
return ordinal;
}
}
public class CharacterOrdering implements Ordering<Character> {
#Override
public int toOrdinal(Character obj) {
return obj;
}
#Override
public Character toObject(int ordinal) {
return (char)ordinal;
}
}
Now you may make your sort method accepting the ordering parameter:
public static <T> void sort(T[] array, Ordering<T> ordering) { ... }
Every time you need to get counts array index by T object, just call ordering.toOrdinal(object). Every time you need to get object by array index, just use ordering.toObject(index). So, for example, instead of
counts[array[i] - min]++;
Use
counts[ordering.toOrdinal(array[i]) - min]++;
And call the sorting method like this:
sort(characterArray, new CharacterOrdering());
sort(integerArray, new IntegerOrdering());

Chapter 13 ex 12 and main project 1. Structure and Algorithm in Java by Frank

import.util.Arrays;
public class AList<T> implements ListInterface<T>{
private T[] list;
private int numberOfEntries;
private static final int DEFAILT_INI_CAPACITY=25;
public AList()
{
this(DEFAILT_INI_CAPACIT);
}
public AList
{
numberOfEntries = 0;
// the cast is safe because the new array contains null entries
#SuppressWarnings("unchecked")
T[] tempList = (T[])new Object[initialCapacity];
list = tempList;
}
public void add(T newEntry) {
ensureCapacity();
list[numberOfEntries] = newEntry;
numberOfEntries++;
} // end add
public int getLength() {
return numberOfEntries;
} // end getLength
public boolean isEmpty() {
return numberOfEntries == 0; // or getLength() == 0
} // end isEmpty
public T[] toArray() {
// the cast is safe because the new array contains null entries
#SuppressWarnings("unchecked")
T[] result = (T[])new Object[numberOfEntries];
for (int index = 0; index < numberOfEntries; index++) {
result[index] = list[index];
} // end for
return result;
} // end toArray
Prolbems from Data Strucutre and Algorithum in Java by Frank.
On chapter 13 exercise 12 I'm stuck on the following:
the following method Reduce the size of the array:
private boolean isTooBig()
This method return true if the number if entries in the list is less than half the size of the array and the size of the array is greater than 20.
The second new method creates a new array that is three quarters the size of the current array and then copies the object in the list of the new array:
private void reduceArray()
My Attempt:
private boolean isTooBig()
{
int half = (2 / getLenght());;
return ((numberOfEntries < half) && (numberOfEntries > 20));
}
private void reduceArray()
{
private T[] list2;
stuck...
}
My question: I do not know what is The array that I am reducing.
After I reduce the array. I do not know how to copy an ArrayList to another ArrayList.
Also I am stuck on Main project one.
1) Write a program that thoroughly tests the class AList.
My attempt:
public class test {
public static void main(String[] args)
{
AList<integer> listOfInt = new AList<integer>();
listOfInt.add(1);
listOfInt.add(2);
System.out.println(listOfInt);
}
The output is the address of listOfInt, but I want the literal value 1,2 to be printed.

Binary Search program will compile and run but does not complete and won't terminate?

I have written a binary Search program as part of a project. It will compile and run but when it gets to the part of the program where it should search the array for the target value (is entered by user) it doesn't do anything it just lets me enter a target value but does not appear to search or terminate.
Here is my code:
/**
*
*/
package ProofOfConcepts;
import java.util.Random;
import java.util.Scanner;
/**
* #author Kirome
*
*/
public class BinarySearch {
static int RandomNum;
static int NumSize;
static int[] arr;
static int rangeOfNum;
static int LookFor;
static Random numGen = new Random();
static Scanner Input = new Scanner(System.in);
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Enter the size of the data set");
NumSize = Input.nextInt();
System.out.println("Enter the range of the random numbers");
rangeOfNum = Input.nextInt();
arr = new int[NumSize];
for (int i = 0; i <= NumSize-1; i++) {
RandomNum = numGen.nextInt(rangeOfNum);
arr[i] = RandomNum;
System.out.println("Number is: " + RandomNum);
}
System.out.println("Enter number you want to search for: ");
LookFor = Input.nextInt();
binarySearch(arr[0], arr.length-1, LookFor, arr);
}
//Binary Search Algorithm
public static int binarySearch(int LowIndex, int HighIndex, int Target, int[] array) {
int MidIndex = (LowIndex + HighIndex)/2;
while (LowIndex <= HighIndex) {
if (array[MidIndex] == Target){
System.out.println("Target is found at: " + array[MidIndex]);
if (array[MidIndex] < Target){
binarySearch(LowIndex, MidIndex-1, Target, array);
}
if (array[MidIndex] > Target){
binarySearch(MidIndex+1, HighIndex, Target, array);
} else {
System.out.println("Target number is not in the array");
}
}
}
System.out.println(array);
return Target;
}
}
Its frustrating because I know it must be something simple to why it does not run properly. Thanks in advance, and p.s. I'm not the best programmer.
If you're going to use binary search, you need sorted data. Randomly distributed data cannot be searched with a binary search.
Rewriting as an answer --
In addition to making sure that your input is sorted, the recursive binary search method should have returns in it so the method can correctly wind back the result to teh original call.
for instance -
if (array[MidIndex] < Target)
return binarySearch(LowIndex, MidIndex-1, Target, array);
else if (array[MidIndex] > Target)
return binarySearch(MidIndex+1, HighIndex, Target, array);
Looks to me like the issue is the use of the while loop combined with recursion. Normally, if you are using recursion to implement a binary search, looping shouldn't be necessary.
Also, as others have said, make sure your array is sorted.
I would try this instead:
public static int binarySearch(int LowIndex, int HighIndex, int Target, int[] array) {
if (LowIndex <= HighIndex) {
int MidIndex = (LowIndex + HighIndex)/2;
if (array[MidIndex] == Target){
return Target;
else if (Target < array[MidIndex])
return binarySearch(LowIndex, MidIndex-1, Target, array);
else
return binarySearch(MidIndex+1, HighIndex, Target, array);
}
return -1; // couldn't find target
}

Categories