I need to use binary search to locate 45.3 in the array. Here's what I have so far.
public class Bsearch {
public static final int NOT_FOUND = -1;
public static int binarySearch(int[] a, int x) {
int low = 0;
int high = a.length - 1;
int mid;
while (low <= high) {
mid = (low + high) / 2;
if (a[mid].compareTo(x) < 0)
low = mid + 1;
else if (a[mid].compareTo(x) > 0)
high = mid - 1;
else
return mid;
}
return NOT_FOUND;
}
public static void main(String[] args) {
int SIZE = 6;
int[] a = new Integer[SIZE] = { 10, -3, 5, 24, 45.3, 10.5 };
System.out.println("45.3 Found" + binarySearch(a, 45.3));
}
}
All my errors seem to be stemming from this area-
int [] a = new Integer [ SIZE ]={ 10,-3,5,24,45.3,10.5 };
System.out.println("45.3 Found" +binarySearch(a, 45.3));
All this is new to me so sorry for any obvious mistakes.
For binary search Data Array should be sorted, and sorted in the right order, but the array you are passing to binarySearch(int[] a, int x) is not sorted so first sort the array and then apply binary search on it.
Also check your logic for binary search, you are comparing middle element with 0 it should be compared with the element to be searched(key)
while(high >= low) {
int middle = (low + high) / 2;
if(data[middle] == key) {
return true;
}
if(data[middle] < key) {
low = middle + 1;
}
if(data[middle] > key) {
high = middle - 1;
}
}
The problem is indeed in this line:
int[] a = new Integer[SIZE] = { 10, -3, 5, 24, 45.3, 10.5 };
There are a number of issues:
You can't assign an Integer[] to an int[] variable. Change it to new int[]
You can't put a floating point number in an array of integers; change your numbers 45.3 and 10.5 to integers.
You have two options in Java: when you create a new array with the new operator, you either specify size of the array, or the contents.
So either:
int[] a = new int[SIZE];
Or
int[] a = new int[] { 10, -3, 5, 24, 45, 10 };
Both will work.
You have to decide whether you want to use primitive types (int) of class wrappers (Integer) and stick to it.
Your method binarySearch takes an int[] as a parameter, but you are using methods (compareTo) that are only available on Integer.
But actually, comparing is much simpler with primitive types:
if (a[mid] < x)
low = mid + 1;
else if (a[mid] > x)
high = mid - 1;
else
return mid;
Related
The following is my code for Merge Sort in JAVA, but the output is not expected.
given input is [49, 1, 3, 200, 2, 4, 70, 5]
The output is :
Merge sort : [2, 4, 49, 1, 3, 70, 5, 200]
Which the number is not sorted. I believe the problem is in the merge method. Can anyone help?
merge_sort method:
private static int[] merge_sort(int[] unsorted_array) {
if (unsorted_array.length < 2) {
return unsorted_array;
}
int mid = unsorted_array.length / 2;
int[] first_array = new int[mid];
int[] second_array = new int[unsorted_array.length - mid];
//Copy element to first and second array.
for (int i = 0; i < mid; i ++) {
first_array[i] = unsorted_array[i];
}
for (int i = 0; i < second_array.length; i++) {
second_array[i] = unsorted_array[mid + i];
}
merge_sort(first_array);
merge_sort(second_array);
int[] sorted_array = merge(first_array, second_array);
return sorted_array;
}
merge method:
private static int[] merge(int[] first_array, int[] second_array) {
int[] result = new int[first_array.length + second_array.length];
int index_result = 0;
int index_first = 0;
int index_second = 0;
while (index_first < first_array.length && index_second < second_array.length) {
if (first_array[index_first] < second_array[index_second]) {
result[index_result] = first_array[index_first];
index_first++;
} else {
result[index_result] = second_array[index_second];
index_second++;
}
index_result++;
}
while (index_first < first_array.length) {
result[index_result] = first_array[index_first];
index_result++;
index_first++;
}
while (index_second < second_array.length) {
result[index_result] = second_array[index_second];
index_result++;
index_second++;
}
return result;
}
You've made a very simple mistake.
Those two following lines are wrong in your code:
merge_sort(first_array);
merge_sort(second_array);
You should write those two lines as follows:
first_array = merge_sort(first_array);
second_array = merge_sort(second_array);
cause, your merge_sort() method returns a sorted array. It does not sort in place the unsorted_array parameter. Rather, it returns the sorted elements in a newly created sorted_array. So, you would get the sorted result from return value of merge_sort() method and then, you should merge them. Rather than doing that, you were just merging two unsorted arrays.
Its not necessary, but you could write as follows for clarification:
int[] sorted_first_array = merge_sort(first_array);
int[] sorted_second_array = merge_sort(second_array);
// and then merge
int[] sorted_array = merge(sorted_first_array, sorted_second_array);
// then return
return sorted_array;
[P.S.]: When you are coding in java, please use java variable and method naming convention. Its easier to read code when you're following convention.
You are not using the sorted intermediate results to merge, instead using the original splitted arrays. Modify your code as below:
first_array = merge_sort(first_array);
second_array = merge_sort(second_array);
int[] sorted_array = merge(first_array, second_array);
Also you don't need to create these intermediate arrays. You just have to pass the low, high pointers to your array to indicate the portions of the array you are sorting and merging.
Like :
private static void merge_sort(int[] unsorted_array, int low, int high) {
if (low == high) return;
int mid = low + ( high - low ) / 2;
merge_sort(unsorted_array, low, mid);
merge_sort(unsorted_array, mid+1, high);
merge(unsorted_array, low, mid, high);
}
where high is inclusive and you call this like : merge_sort(arr, 0, arr.length-1)
My binary search for seeing if an integer is in an array is looping forever, does anyone know why this might be occurring? By the way, I am using a binary search for the first time.
My Java code is here:
import java.util.Scanner;
public class testBeforeLearning {
private int[] array;
private int target;
public testBeforeLearning(int[] array, int target){
this.array = array;
}
private int low;
private int high;
private int mid;
public Boolean actualSearch(){
low = 0;
high = array.length - 1;
while (target != array[mid]){
mid = (low + high)/2;
if (target == array[mid]){
return true;
}
else if(target > array[mid]){
low = mid + 1;
}
else if (target < array[mid]){
high = mid - 1;
}
}
return false;
}
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int[] dataSet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
System.out.println("Please input a number you want to search for in the array:\n");
int target = input.nextInt();
testBeforeLearning binarySearch = new testBeforeLearning(dataSet, target);
System.out.println(binarySearch.actualSearch());
}
}
For some reason, my lower and upper bounds don't seem to be increasing or decreasing, and I am not sure why, does anyone have any ideas why?
Thanks!
you've set your while condition to be target != array[mid]. But since target is uninitialized (defaults to 0) and 0 does not exist in the array, it will go on forever.
you have to set the value of target in testBeforeLearning. On a side note, you should probably also make the while condition low <= high.
I'm trying to write this algorithm in Java following the steps below:(I know other solutions, just trying to figure out this one)
int min_diff = LARGE_NUMBER;
int diff;
for (each subset S of size n/2 of A) {
diff = abs(sum(S) – sum(A-S));
if (diff < min_diff) {
min_diff = diff;
TempSet = S;
}
}
print min_diff, TempSet;
I tried to find all subset permutations of size n/2 using the code from this link: https://www.geeksforgeeks.org/print-subsets-given-size-set/
The code in this link print all permutations. I thought first I need to store the arrays in an ArrayList so I can use them in the for loop, but I couldn't get it to work. The code below gives wrong output (every array is 60 60 60 instead of permutations:
static List<int[]> intArrays = new ArrayList<>();
static void combinationUtil(int[]arr, int n, int r, int index, int[] data, int i)
{
if (index == r) {
intArrays.add(data);
return;
}
if (i >= n)
return;
data[index] = arr[i];
combinationUtil(arr, n, r, index + 1, data, i + 1);
combinationUtil(arr, n, r, index, data, i + 1);
}
static void printCombination(int arr[], int n, int r)
{
int data[] = new int[r];
combinationUtil(arr, n, r, 0, data, 0);
for(int[] arr1:intArrays){
System.out.println(Arrays.toString(arr1));
}
}
public static void main(String[] args)
{
int arr[] = { 10, 20, 30, 40,50,60};
int n=arr.length;
int r=n/2;
printCombination(arr, n, r);
}
Can anyone tell me what's wrong with my code? Or how can I solve this problem following the above steps?
Your problem is when you do intArrays.add(data);
intArrays always contains the reference to data array. The array is passed by reference. You gets {60, 60, 60} because is the last state of data array (the last subset).
To fix the problem you must to do intArrays.add(data.Clone()); if exists Clone function or similar in you language or just implement it yourself.
Code in C#. Sorry I don't have any java compiler installed.
static int[] CloneArray(int[] arr)
{
int[] ret = new int[arr.Length];
for (int i = 0; i < arr.Length; ++i) ret[i] = arr[i];
return ret;
}
I came across a problem such that:
WAP to sort prime numbers smaller than given N by digits. If N is 40,
the output should be 11, 13, 17, 19, 2, 23, 29, 3, 31, 37, 39, 5, 7.
Note: Limit memory use.
Getting primary number was the easy. But I could not figure out an efficient way of lexicographic sorting of array of integer.
public static void getPrimeNumbers(int limit) {
for (int i=2; i<=limit; i++) {
if(isPrime(i)) {
System.out.println(i);
}
}
}
public static boolean isPrime(int number) {
for(int j=2; j<number; j++) {
if(number%j==0) {
return false;
}
}
return true;
}
public static void lexographicSorting() {
int[] input = {2,3,5,7,11,13,17,19};
int[] output = {};
for (int i=0; i<input.length; i++) {
for(int j=0; j<input.length; j++) {
////Stuck at this part.
}
}
}
Java String#compareTo already implements this functionality, you can access it pretty easily by converting your Integer objects to String objects and calling compareTo
Arrays.sort(input, new Comparator<Integer>() {
#Override
int compareTo( Integer x, Integer y ) {
return x.toString().compareTo( y.toString() );
}
};
I can say exactly how memory efficient this would be, you have to create 1 Integer object for each primitive int in your array, then you have to create 1 String object for each Integer object you have. So there is probably a good deal of overhead in object creation.
Given the constraints on the problem, the more efficient way to solve this problem is to not use String and Integer instances at all. One of the directives of the problem is to limit memory usage. In each of the answers so far, there has been a significant impact on memory (converting to and from Integer and String).
Here is a solution that is likely to be faster, and allocates no heap memory at all (although it has recursion so it may have some stack-effect - about the same as Arrays.sort()). This solves the problem from first-principles, it does not allocate a separate array for the results, and thus, it is relatively long compared to other solutions, but, those other solutions hide a mass of complexity that this solution does not have...
// this compare works by converting both values to be in the same 'power of 10',
// for example, comparing 5 and 20, it will convert 5 to 50, then compare 50 and 20
// numerically.
public static final int compareLexographicallyToLimit(final int limit, int a, int b) {
if (a == b) {
return 0;
}
if (a > limit || b > limit || a < 0 || b < 0) {
return a > b ? 1 : -1;
}
int max = Math.max(a, b);
int nextp10 = 1;
while (max > 10) {
max /= 10;
nextp10 *= 10;
}
while (a < nextp10) {
a *= 10;
}
while (b < nextp10) {
b *= 10;
}
return a > b ? 1 : -1;
}
private static void sortByRules(final int[] input, final int limit, final int from, final int to) {
if (from >= to) {
return;
}
int pivot = from;
int left = from + 1;
int right = to;
while (left <= right) {
while (left <= right && compareLexographicallyToLimit(limit, input[left], input[pivot]) <= 0) {
left++;
}
while (left <= right && compareLexographicallyToLimit(limit, input[pivot], input[right]) <= 0) {
right--;
}
if (left < right) {
int tmp = input[left];
input[left] = input[right];
input[right] = tmp;
left++;
right--;
}
}
int tmp = input[pivot];
input[pivot] = input[right];
input[right] = tmp;
sortByRules(input, limit, from, right-1);
sortByRules(input, limit, right+1, to);
}
public static void main(String[] args) {
int[] input = {2,3,5,7,11,13,17,19,31,37,41, 43, 100};
sortByRules(input, 40, 0, input.length - 1);
System.out.println(Arrays.toString(input));
sortByRules(input, 15, 0, input.length - 1);
System.out.println(Arrays.toString(input));
}
The only possible way is to implement your own Comparator where you will convert each of two comparable Integer-s to String objects and do comparison on them.
UPD: Here is an example, how to implement it:
Integer[] input = {2,3,5,7,11,13,17,19};
Arrays.sort(input, new Comparator<Integer>() {
#Override
public int compare(Integer o1, Integer o2) {
return o1.toString().compareTo(o2.toString());
}
});
If you don't want to convert your integer values to strings (which can be wasteful), you can do something like this.
You can sort the numbers based on the most significant digits. See this post for computing the most significant digit of a number: Getting a values most significant digit in Objective C (it should be easy to port to Java).
Essentially you can use that function as part of your Comparator. You'll need a way to break ties (e.g., numbers with the same most significant digit(s)). If two numbers have the same most significant digits you can pluck them off and re-call this function over and over again as many times as necessary (until you can deem one number greater than the other, or until you run out of digits, indicating that they're equal).
Just to add to Hunter McMillen answer, Java 8's syntax allows defining a Comnparator in a much cleaner, leaner, way. Since Arrays.sort(int[]) does not have an overloaded variant that takes a Comparator, boxing the array is necessary in order to use a Comparator. E.g.:
int[] output =
Arrays.stream(input)
.boxed()
.sorted(Comparator.comparing(String::valueOf))
.mapToInt(Integer::intValue)
.toArray();
This question already has answers here:
Finding multiple entries with binary search
(15 answers)
Closed 3 years ago.
I've been tasked with creating a method that will print all the indices where value x is found in a sorted array.
I understand that if we just scanned through the array from 0 to N (length of array) it would have a running time of O(n) worst case. Since the array that will be passed into the method will be sorted, I'm assuming that I can take advantage of using a Binary Search since this will be O(log n). However, this only works if the array has unique values. Since the Binary Search will finish after the first "find" of a particular value. I was thinking of doing a Binary Search for finding x in the sorted array, and then checking all values before and after this index, but then if the array contained all x values, it doesn't seem like it would be that much better.
I guess what I'm asking is, is there a better way to find all the indices for a particular value in a sorted array that is better than O(n)?
public void PrintIndicesForValue42(int[] sortedArrayOfInts)
{
// search through the sortedArrayOfInts
// print all indices where we find the number 42.
}
Ex: sortedArray = { 1, 13, 42, 42, 42, 77, 78 } would print: "42 was found at Indices: 2, 3, 4"
You will get the result in O(lg n)
public static void PrintIndicesForValue(int[] numbers, int target) {
if (numbers == null)
return;
int low = 0, high = numbers.length - 1;
// get the start index of target number
int startIndex = -1;
while (low <= high) {
int mid = (high - low) / 2 + low;
if (numbers[mid] > target) {
high = mid - 1;
} else if (numbers[mid] == target) {
startIndex = mid;
high = mid - 1;
} else
low = mid + 1;
}
// get the end index of target number
int endIndex = -1;
low = 0;
high = numbers.length - 1;
while (low <= high) {
int mid = (high - low) / 2 + low;
if (numbers[mid] > target) {
high = mid - 1;
} else if (numbers[mid] == target) {
endIndex = mid;
low = mid + 1;
} else
low = mid + 1;
}
if (startIndex != -1 && endIndex != -1){
for(int i=0; i+startIndex<=endIndex;i++){
if(i>0)
System.out.print(',');
System.out.print(i+startIndex);
}
}
}
Well, if you actually do have a sorted array, you can do a binary search until you find one of the indexes you're looking for, and from there, the rest should be easy to find since they're all next to each-other.
once you've found your first one, than you go find all the instances before it, and then all the instances after it.
Using that method you should get roughly O(lg(n)+k) where k is the number of occurrences of the value that you're searching for.
EDIT:
And, No, you will never be able to access all k values in anything less than O(k) time.
Second edit: so that I can feel as though I'm actually contributing something useful:
Instead of just searching for the first and last occurrences of X than you can do a binary search for the first occurence and a binary search for the last occurrence. which will result in O(lg(n)) total. once you've done that, you'll know that all the between indexes also contain X(assuming that it's sorted)
You can do this by searching checking if the value is equal to x , AND checking if the value to the left(or right depending on whether you're looking for the first occurrence or the last occurrence) is equal to x.
public void PrintIndicesForValue42(int[] sortedArrayOfInts) {
int index_occurrence_of_42 = left = right = binarySearch(sortedArrayOfInts, 42);
while (left - 1 >= 0) {
if (sortedArrayOfInts[left-1] == 42)
left--;
}
while (right + 1 < sortedArrayOfInts.length) {
if (sortedArrayOfInts[right+1] == 42)
right++;
}
System.out.println("Indices are from: " + left + " to " + right);
}
This would run in O(log(n) + #occurrences)
Read and understand the code. It's simple enough.
Below is the java code which returns the range for which the search-key is spread in the given sorted array:
public static int doBinarySearchRec(int[] array, int start, int end, int n) {
if (start > end) {
return -1;
}
int mid = start + (end - start) / 2;
if (n == array[mid]) {
return mid;
} else if (n < array[mid]) {
return doBinarySearchRec(array, start, mid - 1, n);
} else {
return doBinarySearchRec(array, mid + 1, end, n);
}
}
/**
* Given a sorted array with duplicates and a number, find the range in the
* form of (startIndex, endIndex) of that number. For example,
*
* find_range({0 2 3 3 3 10 10}, 3) should return (2,4). find_range({0 2 3 3
* 3 10 10}, 6) should return (-1,-1). The array and the number of
* duplicates can be large.
*
*/
public static int[] binarySearchArrayWithDup(int[] array, int n) {
if (null == array) {
return null;
}
int firstMatch = doBinarySearchRec(array, 0, array.length - 1, n);
int[] resultArray = { -1, -1 };
if (firstMatch == -1) {
return resultArray;
}
int leftMost = firstMatch;
int rightMost = firstMatch;
for (int result = doBinarySearchRec(array, 0, leftMost - 1, n); result != -1;) {
leftMost = result;
result = doBinarySearchRec(array, 0, leftMost - 1, n);
}
for (int result = doBinarySearchRec(array, rightMost + 1, array.length - 1, n); result != -1;) {
rightMost = result;
result = doBinarySearchRec(array, rightMost + 1, array.length - 1, n);
}
resultArray[0] = leftMost;
resultArray[1] = rightMost;
return resultArray;
}
Another result for log(n) binary search for leftmost target and rightmost target. This is in C++, but I think it is quite readable.
The idea is that we always end up when left = right + 1. So, to find leftmost target, if we can move right to rightmost number which is less than target, left will be at the leftmost target.
For leftmost target:
int binary_search(vector<int>& nums, int target){
int n = nums.size();
int left = 0, right = n - 1;
// carry right to the greatest number which is less than target.
while(left <= right){
int mid = (left + right) / 2;
if(nums[mid] < target)
left = mid + 1;
else
right = mid - 1;
}
// when we are here, right is at the index of greatest number
// which is less than target and since left is at the next,
// it is at the first target's index
return left;
}
For the rightmost target, the idea is very similar:
int binary_search(vector<int>& nums, int target){
while(left <= right){
int mid = (left + right) / 2;
// carry left to the smallest number which is greater than target.
if(nums[mid] <= target)
left = mid + 1;
else
right = mid - 1;
}
// when we are here, left is at the index of smallest number
// which is greater than target and since right is at the next,
// it is at the first target's index
return right;
}
I came up with the solution using binary search, only thing is to do the binary search on both the sides if the match is found.
public static void main(String[] args) {
int a[] ={1,2,2,5,5,6,8,9,10};
System.out.println(2+" IS AVAILABLE AT = "+findDuplicateOfN(a, 0, a.length-1, 2));
System.out.println(5+" IS AVAILABLE AT = "+findDuplicateOfN(a, 0, a.length-1, 5));
int a1[] ={2,2,2,2,2,2,2,2,2};
System.out.println(2+" IS AVAILABLE AT = "+findDuplicateOfN(a1, 0, a1.length-1, 2));
int a2[] ={1,2,3,4,5,6,7,8,9};
System.out.println(10+" IS AVAILABLE AT = "+findDuplicateOfN(a2, 0, a2.length-1, 10));
}
public static String findDuplicateOfN(int[] a, int l, int h, int x){
if(l>h){
return "";
}
int m = (h-l)/2+l;
if(a[m] == x){
String matchedIndexs = ""+m;
matchedIndexs = matchedIndexs+findDuplicateOfN(a, l, m-1, x);
matchedIndexs = matchedIndexs+findDuplicateOfN(a, m+1, h, x);
return matchedIndexs;
}else if(a[m]>x){
return findDuplicateOfN(a, l, m-1, x);
}else{
return findDuplicateOfN(a, m+1, h, x);
}
}
2 IS AVAILABLE AT = 12
5 IS AVAILABLE AT = 43
2 IS AVAILABLE AT = 410236578
10 IS AVAILABLE AT =
I think this is still providing the results in O(logn) complexity.
A Hashmap might work, if you're not required to use a binary search.
Create a HashMap where the Key is the value itself, and then value is an array of indices where that value is in the array. Loop through your array, updating each array in the HashMap for each value.
Lookup time for the indices for each value will be ~ O(1), and creating the map itself will be ~ O(n).
Find_Key(int arr[], int size, int key){
int begin = 0;
int end = size - 1;
int mid = end / 2;
int res = INT_MIN;
while (begin != mid)
{
if (arr[mid] < key)
begin = mid;
else
{
end = mid;
if(arr[mid] == key)
res = mid;
}
mid = (end + begin )/2;
}
return res;
}
Assuming the array of ints is in ascending sorted order; Returns the index of the first index of key occurrence or INT_MIN. Runs in O(lg n).
It is using Modified Binary Search. It will be O(LogN). Space complexity will be O(1).
We are calling BinarySearchModified two times. One for finding start index of element and another for finding end index of element.
private static int BinarySearchModified(int[] input, double toSearch)
{
int start = 0;
int end = input.Length - 1;
while (start <= end)
{
int mid = start + (end - start)/2;
if (toSearch < input[mid]) end = mid - 1;
else start = mid + 1;
}
return start;
}
public static Result GetRange(int[] input, int toSearch)
{
if (input == null) return new Result(-1, -1);
int low = BinarySearchModified(input, toSearch - 0.5);
if ((low >= input.Length) || (input[low] != toSearch)) return new Result(-1, -1);
int high = BinarySearchModified(input, toSearch + 0.5);
return new Result(low, high - 1);
}
public struct Result
{
public int LowIndex;
public int HighIndex;
public Result(int low, int high)
{
LowIndex = low;
HighIndex = high;
}
}
public void printCopies(int[] array)
{
HashMap<Integer, Integer> memberMap = new HashMap<Integer, Integer>();
for(int i = 0; i < array.size; i++)
if(!memberMap.contains(array[i]))
memberMap.put(array[i], 1);
else
{
int temp = memberMap.get(array[i]); //get the number of occurances
memberMap.put(array[i], ++temp); //increment his occurance
}
//check keys which occured more than once
//dump them in a ArrayList
//return this ArrayList
}
Alternatevely, instead of counting the number of occurances, you can put their indices in a arraylist and put that in the map instead of the count.
HashMap<Integer, ArrayList<Integer>>
//the integer is the value, the arraylist a list of their indices
public void printCopies(int[] array)
{
HashMap<Integer, ArrayList<Integer>> memberMap = new HashMap<Integer, ArrayList<Integer>>();
for(int i = 0; i < array.size; i++)
if(!memberMap.contains(array[i]))
{
ArrayList temp = new ArrayList();
temp.add(i);
memberMap.put(array[i], temp);
}
else
{
ArrayList temp = memberMap.get(array[i]); //get the lsit of indices
temp.add(i);
memberMap.put(array[i], temp); //update the index list
}
//check keys which return lists with length > 1
//handle the result any way you want
}
heh, i guess this will have to be posted.
int predefinedDuplicate = //value here;
int index = Arrays.binarySearch(array, predefinedDuplicate);
int leftIndex, rightIndex;
//search left
for(leftIndex = index; array[leftIndex] == array[index]; leftIndex--); //let it run thru it
//leftIndex is now the first different element to the left of this duplicate number string
for(rightIndex = index; array[rightIndex] == array[index]; rightIndex++); //let it run thru it
//right index contains the first different element to the right of the string
//you can arraycopy this [leftIndex+1, rightIndex-1] string or just print it
for(int i = leftIndex+1; i<rightIndex; i++)
System.out.println(array[i] + "\t");