getting compilation error in binary search implementation - algorithm

I am implementing binary search algorithm , but i am facing return statement issue.Here is my method binarySearch() implementation
public static int binarySearch(int[] a, int n, int x) {
int start = 0;
int end = n - 1;
while (start <= end) {
int mid = (start + end) / 2;
if (a[mid] == x) {
return mid;
} else if (a[mid] < x) {
start = mid + 1;
} else {
end = mid - 1;
}
}
}
Any help would be appreciated.
Thanks

It is possible that this method is called on an array that does not have the value.
You can
return 0;
at the end of the method call. Or...
throw new RuntimeException("Value not found in array");
Whichever is right for this code.

Your function does not return all the paths.
public static int binarySearch(int[] a, int n, int x) {
int start = 0;
int end = n - 1;
int result = 0; // Or something you define yourself for not found case
while (start <= end) {
int mid = (start + end) / 2;
if (a[mid] == x) {
result = mid;
} else if (a[mid] < x) {
start = mid + 1;
} else {
end = mid - 1;
}
}
return result;
}

Related

CSES food division problem solving approach

Has anyone tried to solve this particular problem? https://cses.fi/problemset/task/1189
Can someone help with an approach?
This works but doesn't optimize the steps
Tried recursion, but since the array 'a' needs to be updated, not sure how recursion can work in this case.
private int findMinSteps(int[] a, int[] b, int n) {
int cnt = 0;
do {
for(int i=1; i <= n; i++) {
if(a[i] == b[i]) continue;
if(a[i] > b[i]) { //we can give
if(a[left(i)] < b[left(i)]) { //give to left
a[i] -= 1;
a[left(i)] += 1;
cnt ++;
} else /*if(a[right(i)] < b[right(i)])*/ { //give to right
a[i] -= 1;
a[right(i)] += 1;
cnt ++;
}
} else { //we have to receive
if(a[left(i)] > b[left(i)]) { //receive from left`
a[i] += 1;
a[left(i)] -= 1;
cnt ++;
} else { //receive from right
a[i] += 1;
a[right(i)] -= 1;
cnt ++;
}
} //if-else
} //for
} while(!Arrays.equals(a, b));
return cnt;
} //findMinSteps
Here's a recursive solution that doesn't work either
private int findMinSteps(int[] a, int[] b, int n) {
/*if only one kid or zero kids are there, there is no mis-match
*because the total amount of food is correct
*/
//System.out.println(Arrays.toString(a));
//System.out.println(Arrays.toString(b));
if(n < 1)
return 0;
if(a[n] == b[n])
return findMinSteps(a, b, n-1);
if(a[n] > b[n]) {
//At each step a child can give 1 unit of food to neighbor
int l = left(n);
int r = right(n);
a[n] -= 1;
if(a[l] < b[l]) {
a[l] += 1;
} else if(a[r] < b[r]) {
a[r] += 1;
}
return 1+findMinSteps(a, b, n-1);
} else
return findMinSteps(a, b, n-1);
}

Challenge from "leetcode162" to find peak element. Why this case can't pass?

My code is as follows. I used binary search for the problem.
38/58 test cases can pass, yet this can not pass any way:
[3,4,3,2,1], I calculated it on paper, and the process is as below:
end=4,mid=0+(4-0)/2=2,start=2.
But in the case above, start should be 1.
I don't know how to revise my code.
class Solution {
public int findPeakElement(int[] nums) {
if (nums.length == 0 ||nums.length == 1) {
return 0;
}
int start = 0;
int end = nums.length - 1;
int mid;
//binary search
while (start + 1 < end) {
mid = start + (end - start) / 2;
if (nums[start] < nums[start + 1]) {
start = mid;
}
else {
end = mid;
}
}
System.out.println ("start=" + start);
System.out.println ("end=" + end);
System.out.println ("nums[start]=" + nums[start]);
System.out.println ("nums[end]=" + nums[end]);
if (nums[start] < nums[end]) {
return end;
}
else {
return start;
}
}
}
Your solution is a little over complicated, here is a more concise solution. If you go line by line you will realize that it needs less checks than you think.
mid is tricky, but if start and end set properly, you don't need to add the start val.
class Solution {
public int findPeakElement(int[] nums) {
if (nums.length <= 1){
return 0;
}
int start = 0;
int end = nums.length - 1;
int mid = 0;
//binary search
while (start < end) {
mid = (start + end) / 2;
if (nums[mid] > nums[mid + 1]) {
end = mid;
}
else if (nums[mid] < nums[mid + 1]) {
start = mid+1;
}
}
return start;
}
}
You should change
nums[start] < nums[start + 1]
to
nums[mid] < nums[mid + 1]
but, your algorithm will work only when the array 'nums' is stricktly increasing and decreasing.
and
mid = start + (end - start) / 2;
is totally same with
mid = (start + end) / 2;
so i think it's better and simpler

Binary search of a Matrix

Write an efficient algorithm that searches for a value in an m x n
matrix.
This matrix has the following properties:
-Integers in each row are sorted from left to right. -The first integer
of each row is greater than or equal to the last integer of the
previous row. Example:
Consider the following matrix:
[
[1, 3, 5, 7],
[10, 11, 16, 20], [23, 30, 34, 50] ] Given
target = 3, return 1 ( 1 corresponds to true )
Return 0 / 1 ( 0 if the element is not present, 1 if the element is
present ) for this problem
My solution works on NetBeans but fails on the website. Any help will be appreciated.
https://www.interviewbit.com/problems/matrix-search/
public class Solution {
public int searchMatrix(ArrayList<ArrayList<Integer>> a, int b) {
int r = a.size();
int c = a.get(0).size();
int start = 0;
int end = r - 1;
// default value is last row for edge case
int biRow = r -1; // row to search column
//binary search 1st value of rows
while (start <= end) {
int mid = (start + end) / 2;
if (b == a.get(mid).get(0)) {
return 1;
}
if (a.get(mid).get(0) < b && b < a.get(end).get(0)) {
if (mid + 1 >= end) {
biRow = mid;
break;
}
} if (b < a.get(mid).get(0)) {
end = mid - 1;
} else {
start = mid + 1;
}
}
//binary search column of biRow
start = 0;
end = c-1;
while (start <= end) {
int mid = (start + end) / 2;
if (b == a.get(biRow).get(mid)) {
return 1;
}
if (b < a.get(biRow).get(mid)) {
end = mid - 1;
} else {
start = mid + 1;
}
}
return 0;
}
}
Okay, the first thing you MUST NOT do is that, you cannot physically concat the matrix into a 1D vector, as this is O(N*M) which is linear and not what we want.
// Easy but TLE code
int Solution::searchMatrix(vector<vector<int> > &A, int B) {
vector<int> v;
for(auto a : A) v.insert(v.end(), a.begin(), a.end());
return binary_search(v.begin(), v.end(), B);
}
So the point is, you have to do binary search directly on the matrix, and that is pretty much the same (except you have to write binary search your own now).
As you did not really access all of the elements, this is O(lg (N*M))
// Less Easy but AC code
int Solution::searchMatrix(vector<vector<int> > &A, int B) {
int m = A.size(), n = A[0].size(), lo = 0, hi = m*n-1, mi, row, col;
while(lo <= hi){
mi = lo + ((hi-lo) >> 1);
row = mi / n;
col = mi % n;
if(A[row][col] == B) return 1;
else if(A[row][col] > B) hi = mi - 1;
else lo = mi + 1;
}
return 0;
}
I think the shared program seems to have a logical error.
When updating the end value in the first while loop, if the end value is equal to start, biRow can not be updated.
It worked well when I updated the code like below.
public class Solution {
public int searchMatrix(ArrayList<ArrayList<Integer>> a, int b) {
int r = a.size();
int c = a.get(0).size();
int start = 0;
int end = r - 1;
// default value is last row for edge case
int biRow = r -1; // row to search column
//binary search 1st value of rows
int mid = 0;
while (start <= end) {
mid = (start + end) / 2;
if ( b >= a.get(mid).get(0) && b <= a.get(mid).get(c-1)) {
break;
}
if (b < a.get(mid).get(0)) {
end = mid-1;
} else {
start = mid+1;
}
}
biRow = mid;
//binary search column of biRow
start = 0;
end = c-1;
while (start <= end) {
mid = (start + end) / 2;
if (b == a.get(biRow).get(mid)) {
return 1;
}
if (b < a.get(biRow).get(mid)) {
end = mid - 1;
} else {
start = mid + 1;
}
}
return 0;
}
}
There is logical error in your row search loop. I made a correction and I also added the boundary conditions.Time complexity of this algorithm is O(logN).
public class Solution {
public int searchMatrix(ArrayList<ArrayList<Integer>> a, int b) {
int r = a.size();
int c = a.get(0).size();
// return 0 if b is less than 1st element or greater than last element
if (b < a.get(0).get(0) || b > a.get(r - 1).get(c - 1))
return 0;
int start = 0;
int end = r - 1;
// default value is last row for edge case
int biRow = r - 1; // row to search column
// binary search 1st value of rows
while (start <= end) {
int mid = (start + end) / 2;
if (b == a.get(mid).get(0)) {
return 1;
}
if (b >= a.get(mid).get(0) && b <= a.get(mid).get(c - 1)) {
{
biRow = mid;
break;
}
}
if (b < a.get(mid).get(0)) {
end = mid - 1;
} else {
start = mid + 1;
}
}
// binary search column of biRow
start = 0;
end = c - 1;
while (start <= end) {
int mid = (start + end) / 2;
if (b == a.get(biRow).get(mid)) {
return 1;
}
if (b < a.get(biRow).get(mid)) {
end = mid - 1;
} else {
start = mid + 1;
}
}
return 0;
}
}
Since the rows and columns are sorted, a binary search will be proper as you said. This is a binary search(on a matrix) implementation in Ruby
def binary_search_on_matrix(matrix,target)
row_size = matrix.size
column_size = matrix[0].size
left_index = 0
right_index = (row_size * column_size) - 1
while (left_index <= right_index)
mid_point = left_index + ((right_index - left_index) / 2)
row = mid_point / column_size
col = mid_point % column_size
value = matrix[row][col]
if (value == target)
return true
elsif (value > target)
right_index = mid_point - 1
else
left_index = mid_point + 1
end
end
return false
end
You can first convert your 2D array into 1D array and perform binary search operation. You can refer the code given below:
void search(int a[][10],int search,int m,int n)
{
int arr[100],i=0,j=0,k=-1;
for(i=0;i<m;i++)
for(j=0;j<n;j++)
arr[++k] = a[i][j];
int first = 0 , last = k-1 , middle = (first+last)/2;
while (first <= last)
{
if(arr[middle] < search)
{
first = middle + 1;
}
else if(arr[middle] == search)
{
printf("\n Element found at position:( %d , %d")",(middle/n)+1,(middle%n)+1);
printf(" \n Row : %d",(middle/n)+1);
printf("\n column : %d",(middle%n)+1);
break;
}
else
{
last = middle - 1;
}
middle = (first + last)/2;
}
if(first > last)
{
printf("\n Element not found! ");
}
}
This function prints the row and column of element to be searched if it exists.You can modify this code, if You want the function to return a value depending on the search operation.

Algorithm for Adding/Subtracting numbers to find if number can be made?

I was wondering if there is an efficient premade algorithm for determining if the sum/difference of a group of numbers can equal a different number. Example:
5, 8, 10, 2, using + or -, to equal 9.
5 - 8 = -3 + 10 = 7 + 2 = 9
If there is a preexisting algorithm, what is it called. If not, I can figure out how to program it, though it may not be efficient.
Thank you!
Yeah, this is basically knapsack problem, but it can be computed in pseudopolynomial time using dynamic programming.
I did it few month ago, so maybe this java code can help you, if you want to implement it :
public void solve() {
while (this.isEnd() == false) {
int priceSum = this.getItemsInstance().getTotalPrice()/divide;
int numOfItems = this.getItemsInstance().itemCount();
int maxWeight = this.getItemsInstance().getMaxWeight();
int[][] array = new int[numOfItems + 1][priceSum + 1];
boolean[][] arrayCounted = new boolean[numOfItems + 1][priceSum + 1];
for (int i = 0; i < numOfItems + 1; i++) {
array[i][0] = 0;
arrayCounted[i][0] = true;
}
int max = 0;
int price = 0;
for (int j = 1; j < priceSum + 1; j++) {
for (int i = 1; i < numOfItems + 1; i++) {
int temp = W(i, j, array, arrayCounted);
if (temp <= maxWeight) {
max = temp;
price = j;
}
}
}
}
}
private int W(int i, int c, int[][] array, boolean[][] arrayCounted) {
if (c < 0) {
return MAX_PRICE / divide;
}
if (i == 0) {
if (c == 0) {
return 0;
} else {
return MAX_PRICE / divide;
}
}
if (arrayCounted[i][c]) {
return array[i][c];
}
arrayCounted[i][c] = true;
array[i][c] = Math.min(W(i - 1, c, array, arrayCounted), W(i - 1, c - this.items[i - 1].price/divide, array, arrayCounted) + this.items[i - 1].weight);
return array[i][c];
}
its not an NP problem, if the problem is to find a given number from adding or subtracting each elements of a list/array. if you think about AP. here is a sample code in C++
int Np( int mn, list<int>a, int c )
{
int size = a.size(), rst = 0, maxI = 0;
std::list<int>::iterator it;
while( size > c )
{
a.sort();
maxI += a.back();
a.pop_back();
rst = 0;
for( auto ele : a )
{
rst += ele;
cout << rst << endl;
}
if( (rst - maxI) == mn or (maxI - rst) == mn or (maxI + rst) == mn )
{
return mn;
}
size--;
}
return rst;
}
this should help. i think.
I actually wrote a simple java program, I was not actually aware of knapsack strategies. This is my own solution. Hope this helps
import java.util.ArrayList;
import java.util.List;
public class Puzzle {
public static void main(String[] args) {
int targetNumber = 0;
int min = 2147483647;
int[] numbers = {-10, -30, -20, -50};
//int[] numbers = {0,0,0,0};
//int[] numbers = {7, 2, 10};
//int[] numbers = {1, 2, 3, 4, 5};
//int[] numbers = {1000, 2, 3, 4, 100};
char set[] = {'+', '-'};
min = getNumberClosestToTarget(numbers, set, min, targetNumber);
System.out.println(String.format(" %d is closest to %d", min, targetNumber));
}
private static int getNumberClosestToTarget(int[] numbers, char[] set, int min, int targetNumber) {
List<String> operators = new ArrayList<>();
computeAllOperatorsCombination(set, "", set.length, numbers.length - 1, operators);
for (String operatorString : operators) {
String[] ops = operatorString.split("");
int sum = computeSum(numbers, ops, numbers.length - 1);
min = getClosestToTarget(min, targetNumber, sum);
}
return min;
}
static int computeSum(int[] numbers, String[] operators, int index) {
int result = numbers[index];
if (index == 0) {
return result;
} else {
switch (operators[index - 1]) {
case "+":
return computeSum(numbers, operators, index - 1) + result;
case "-":
return computeSum(numbers, operators, index - 1) - result;
}
return result;
}
}
static void computeAllOperatorsCombination(char set[], String prefix, int n, int k, List<String> result) {
if (k == 0) {
result.add(prefix);
return;
}
for (int i = 0; i < n; i++) {
String newPrefix;
newPrefix = prefix + set[i];
computeAllOperatorsCombination(set, newPrefix, n, k - 1, result);
}
}
private static int getClosestToTarget(int min, int targetNumber, int r) {
int distance = Math.abs(targetNumber - r) < Math.abs(r - targetNumber) ? Math.abs(targetNumber - r) : Math.abs(r - targetNumber);
if (distance < Math.abs(min)) {
min = distance;
if (r < 0) {
min = -distance;
}
}
return min;
}
}

Implementation of Quick Sort

#include<stdio.h>
#include<iostream.h>
#include<conio.h>
void quicks(int *arr,int x,int pivot,int lo,int hi);
void swap1(int *x,int *y);
int main()
{
int *arr = new int[7];
arr[0] = 23;
arr[1] = 3;
arr[2] = -23;
arr[3] = 45;
arr[4] = 12;
arr[5] = 76;
arr[6] = -65;
quicks(arr,7,0,1,6);
for(int i = 0;i<7;i++)
std::cout << arr[i] <<"\t";
getch();
return 0;
}
void quicks(int *arr,int x,int pivot,int lo,int hi)
{
int i = lo,j = hi;
if(pivot < x-1)
{
while(i <= hi)
{
if(arr[i] <= arr[pivot])
i++;
else
break;
}
while(j >= lo)
{
if(arr[j] >= arr[pivot])
j--;
else
break;
}
if( i > j)
{
swap1(&arr[j],&arr[pivot]);
lo = pivot+1;
hi = x - 1;
quicks(arr,x,pivot,lo,hi);
}
else if(i == j)
{
pivot = pivot + 1;
lo = pivot+1;
hi = x - 1;
quicks(arr,x,pivot,lo,hi);
}
else if(i < j)
{
swap1(&arr[j],&arr[i]);
lo = i + 1;
hi = j - 1;
quicks(arr,x,pivot,lo,hi);
}
}
else
{
printf("\nDONE\n");
}
}
void swap1(int *x,int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
Hi,
I have written a program to implement Quick sort.But the program is going into an infinite loop.In the Quicks function,the while loops for incrementing and decrementing i and j are the problem.Can anybody tell me what is wrong with this Implementation of QUick Sort.
Do a quick dry run using your input and the algorithm, you'll notice you run into an infinite cycle after a while.
You are starting the loop from quicks(arr,7,0,1,6);. Try instead by setting low to the "rightmost" element, that is 0. This won't definitely solve your problem as the algorithm seems really flawed, with the position of high not changing at all, and i moving all the way to high. You're trying to complicate a very simple task.
i would go from lo to pivot. And j from hi to pivot. After the pivot is found to be in the right place, you'll move forward pivot and lo by 1, and repeat the process.
Take a look at this image, you'll get an idea of the algo required:

Resources