I've been trying to learn algorithms and as part of this I have been trying to code binary search and the logic seems fine. The code doesn't terminate and the IDE stays idle forever. I don't understand what I'm doing wrong. Any help is appreciated. Thanks in advance!
public class BinarySearch {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
int no = 5;
System.out.print(binSearch(arr, no, 0, arr.length - 1));
}
private static boolean binSearch(int[] arr, int no, int start, int end) {
while(start <= end) {
int mid = (start + end) / 2;
if (arr[mid] == no) {
return true;
} else if (no > arr[mid]) {
binSearch(arr, no, mid + 1, end);
} else if(no < arr[mid]) {
binSearch(arr, no, start, mid - 1);
}
}
return false;
}
}
You are missing the return on the two recursive calls:
private static bool binSearch(int[] arr, int no, int start, int end) {
while(start <= end) {
int mid = (start + end) / 2;
if (arr[mid] == no) {
return true;
} else if (no > arr[mid]) {
return binSearch(arr, no, mid + 1, end);
} else if(no < arr[mid]) {
return binSearch(arr, no, start, mid - 1);
}
}
return false;
}
You could also consider writing it in a non-recursive loop.
okay so i think we review recursion a bit
binSearch(arr, num, start, end){
while (start<=end){
int mid = (start+end)/2;
if (arr[mid] == no) {
return true #when it finally matches return true
}
else if (arr[mid] > no) {
binSearch(arr, no, start, mid-1) #call binSearch for new value
}
}
}
Just to illustrate recursion, imagine we want some value B for an input A. Now imagine a node or some point as an origin that represents our input A. For every point or node that follows after A is some step we take towards finding the value B.
Once we find the value that we want, the structure of our approach can be illustrated as a single graph with one direction. A --> C --> --> D --> B
That is essentially how recursion works. Now first, lets take a look at your else if statement. When your parameters meet one of the else if conditions you make a call to your binSearch method.
What this does is basically create a new point of origin rather than working off the initial one. So lets say at iteration number 3 you finally meet your boolean condition and it returns true. But where does it return true to?
Only the last call or the most recent call that was made to binSearch. Lets call it iteration 2.
Now once the return value is made it simply moves on to the next block of code which brings us to your while loop. The only way your code can move on to the next block of code (which is returning the false value), is to break out of the while loop, ie. have your start value be greater than your end value.
But remember, we are on iteration 2. And iteration 2 was given the values for start and end that satisfied the while-loop so it loops again and whatever else-if statement iteration 2 landed on before the final iteration that returned true, it will keep repeating indefinitely.
The obvious solution as mentioned above is to put 'return' before the call is made as that will return all the way back to the original call to binSearch.
Also, the while loop is not necessary unless you are doing it without recursion.
I have some problems with recursion and to understand it I'm trying to make up questions for myself and solve them. This particular question has gotten me confused:
consider this as an input in the form of a string:
[[a,b,c],[[d]],[[e,f]],[g],h,i,[[j,[k,l]]]]
the goal is to find the total number of things in the lists and the lists them self.for this example the result would be:12+10 = 22
note that the input is not an array,it is a string.Also instead of a,b,...
anything can be used,like numbers,strings etc.
[12345,0.34,["afv",24]]
This is my idea but I will mention why I cant implement it:
We write a function that starts iterating the string.It should count the total thing between [ and ].whenever the function reaches a [ it will recall itself to iterate through the remaining string.This way it can go deeper into the arrays.
These are my problems:
I don't know whether my idea is correct or not.
If my idea is correct,what is the base case.
How can I make sure that it counts all the things inside regardless of in what are they?(I mean how can I make sure it treats numbers,strings etc the same)
I think the body of the function should look like this(I'm using java here but I don't think the language is very important here):
public static int counter(String a){
int sum = 0;
//some code to iterate the string
//some code to check the conditions and if needed call the method
//some code to add the number of objects and arrays to sum
return sum;
}
If the code should like what I said then how can I fill the body?
Thank you for your time.
Depending how you design your recursive algorithm and size of input, you may run into the common problem of recursive stack overflow, where you have very deep recursion and run out of memory space
This is a different iterative pythonic solution if you do not have to use recursion but you should be able to transpose this to Java.
You want to increment you count for every item that is separated by commas. However, if that element has ']' characters, you know that it is a part of a embedded list. By counting the closing braces and the element, you can get the total.
Updated to handle strings with embedded commas
# Function for removing the chars between apostrophes
def remove(s,c):
while(s.find(c) != -1):
i = s.find(c) # find the first instance of c but ' or " in our case
i2 = s.find(c,i+1) # find the second instance
s = s[0:i]+s[i2+1:] # Remove the string
return s
return s
s = "[['a,b,c'],[1,2,3]]"
s = s[:-1] # remove the last list char
total = 0
s = remove(s,'\'')
s = remove(s,'"')
l = s.split(',')
for el in l:
total+=1
total+= el.count(']')
print(total)
Since you don't care about parsing the actual contents of the lists (for that you would implement a recursive descent parser), you can instead implement a simple state machine.
Here's a very rough, partial implementation in pseudo code just to give you some idea about how you might implement this. Ideally you would have more states to detect syntax errors:
int lists, elements = 0;
state = normal;
foreach (char c in input)
{
switch state
case normal:
if (c == '[')
lists++;
else if (c == ']')
// do nothing
else if (c == ',')
// do nothing (will only count [ and , on elements)
else if (c == '"')
elements++;
state = quoted_element
else
elements++;
state = element;
break;
case quoted_element:
if (c == '"')
state = element;
break;
case element:
if (c == '"' || c == '[')
exception("Syntax error");
else if (c == ",")
elements++;
else if (c == "]")
state = normal;
break;
}
Here's a recursion in JavaScript that might give you some ideas.
function f(s){
function nextIndexafterStr(i){
while (!(s[i] == "\"" && s[i-1] != "\\"))
i++;
return i + 1;
}
function nextIndexafterNum(i){
while (![",", "]"].includes(s[i]))
i++;
return i;
}
// Returns [numArrays, numElements, endIndex]
// Assumes valid input
function g(i, as, es){
// base case
if (s[i] == "]" || i == s.length)
return [as, es, i];
if (s[i] == ",")
return g(i + 1, as, es);
// a list
if (s[i] == "["){
const [aas, ees, endIndex] = g(i + 1, 0, 0);
return g(endIndex + 1, as + 1 + aas, es + ees);
}
// string element
if (s[i] == "\"")
return g(nextIndexafterStr(i + 1), as, es + 1);
// number or variable-name element
return g(nextIndexafterNum(i), as, es + 1);
}
const [as, es, _] = g(0, 0, 0);
return as + es;
}
var a = [12345,0.34,["af\"v",24]];
var b = "[[a,b,c],[[d]],[[e,f]],[g],h,i,[[j,[k,l]]]]";
a = JSON.stringify(a);
console.log(a);
console.log(f(a));
console.log(b);
console.log(f(b));
I'm trying to write an algorithm for finding the index of the closest value that is lesser than or equal to the search value in a sorted array. In the example of the array [10, 20, 30], the following search values should output these indexes:
searchValue: 9, index: -1
searchValue: 10, index: 0
searchValue: 28, index: 1
searchValue: 55555, index: 2
I want to use binary search for logarithmic runtime. I have an algorithm in C-esque psuedocode, but it has 3 base cases. Can these 3 base cases be condensed into 1 for a more elegant solution?
int function indexOfClosestLesser(array, searchValue, startIndex, endIndex) {
if (startIndex == endIndex) {
if (searchValue >= array[startIndex]) {
return startIndex;
} else {
return -1;
}
}
// In the simplistic case of searching for 2 in [0, 2], the midIndex
// is always 0 due to int truncation. These checks are to avoid recursing
// infinitely from index 0 to index 1.
if (startIndex == endIndex - 1) {
if (searchValue >= array[endIndex]) {
return endIndex;
} else if (searchValue >= array[startIndex]) {
return startIndex;
} else {
return -1;
}
}
// In normal binary search, this would be the only base case
if (startIndex < endIndex) {
return -1;
}
int midIndex = endIndex / 2 + startIndex / 2;
int midValue = array[midIndex];
if (midValue > searchValue) {
return indexOfClosestLesser(array, searchValue, startIndex, midIndex - 1);
} else if (searchValue >= midValue) {
// Unlike normal binary search, we don't start on midIndex + 1.
// We're not sure whether the midValue can be excluded yet
return indexOfClosestLesser(array, searchValue, midIndex, endIndex);
}
}
Based on your recursive approach, I would suggest the following c++ snippet that reduces the number of different cases a bit:
int search(int *array, int start_idx, int end_idx, int search_val) {
if( start_idx == end_idx )
return array[start_idx] <= search_val ? start_idx : -1;
int mid_idx = start_idx + (end_idx - start_idx) / 2;
if( search_val < array[mid_idx] )
return search( array, start_idx, mid_idx, search_val );
int ret = search( array, mid_idx+1, end_idx, search_val );
return ret == -1 ? mid_idx : ret;
}
Basically it performs a normal binary search. It only differs in the return statement of the last case to fulfill the additional requirement.
Here is a short test program:
#include <iostream>
int main( int argc, char **argv ) {
int array[3] = { 10, 20, 30 };
std::cout << search( array, 0, 2, 9 ) << std::endl;
std::cout << search( array, 0, 2, 10 ) << std::endl;
std::cout << search( array, 0, 2, 28 ) << std::endl;
std::cout << search( array, 0, 2, 55555 ) << std::endl;
return 0;
}
The output is as desired:
-1
0
1
2
Frankly speaking, I find the logic of finding a number greater than a given number a lot easier than the logic needed to find numbers less than or equal to a given number. Obviously, the reason behind that is the extra logic (that forms the edge cases) required to handle the duplicate numbers (of given num) present in the array.
public int justGreater(int[] arr, int val, int s, int e){
// Returns the index of first element greater than val.
// If no such value is present, returns the size of the array.
if (s >= e){
return arr[s] <= N ? s+1 : s;
}
int mid = (s + e) >> 1;
if (arr[mid] < val) return justGreater(arr, val, mid+1, e);
return justGreater(arr, val, s, mid);
}
and then to find the index of the closest value that is lesser than or equal to the search value in a sorted array, just subtract the returned value by 1:
ans = justGreater(arr, val, 0, arr.length-1) - 1;
Trick
The trick here is to search for searchValue + 1 and return the the found index as index - 1 which is left - 1 in the code below
For example if we search for 9 in [10, 20, 30]. The code will look for 10 and return that it's present at 0th index and we return 0-1 which is -1
Similarly if we try to search for 10 in the above example it will search for 10 + 1 and return 1st index and we return 1-1 which is 0
Code
def binary_search(array, searchValue, startIndex=0, endIndex=2 ** 32):
"""
Binary search for the closest value less than or equal to the search value
:param array: The given sorted list
:param searchValue: Value to be found in the array
:param startIndex: Initialized with 0
:param endIndex: Initialized with 2**32
:return: Returns the index closest value less than or equal to the search value
"""
left = max(0, startIndex)
right = min(len(array), endIndex)
while left < right:
mid = (left + right) // 2
if array[mid] < searchValue + 1:
left = mid + 1
else:
right = mid
return left - 1
It can also be done in a single line with the standard library.
import bisect
def standard_binary_search(array, searchVal):
return bisect.bisect_left(array, searchVal + 1) - 1
Testing
Testing the test cases provided by OP
array = [10, 20, 30]
print(binary_search(array, 9))
print(binary_search(array, 10))
print(binary_search(array, 28))
print(binary_search(array, 5555))
Results
-1
0
1
2
I created a linear search to test the binary search.
def linear_search(array, searchVal):
ans = -1
for i, num in enumerate(array):
if num > searchVal:
return ans
ans = i
return ans
And a function to test all the binary search functions above.
Check for correctness
def check_correctness(array, searchVal):
assert binary_search(array, searchVal) == linear_search(array, searchVal)
assert binary_search(array, searchVal) == standard_binary_search(array, searchVal)
return binary_search(array, searchVal)
Driver Function
nums = sorted(
[460, 4557, 1872, 2698, 4411, 1730, 3870, 4941, 77, 7789, 8553, 6011, 9882, 9597, 8060, 1518, 8210, 380, 6822, 9022,
8255, 8977, 2492, 5918, 3710, 4253, 8386, 9660, 2933, 7880, 615, 1439, 9311, 3526, 5674, 1899, 1544, 235, 3369,
519, 8018, 8489, 3093, 2547, 4903, 1836, 2447, 570, 7666, 796, 7149, 9623, 681, 1869, 4381, 2711, 9882, 4348, 4617,
7852, 5897, 4135, 9471, 4202, 6630, 3037, 9694, 9693, 7779, 3041, 3160, 4911, 8022, 7909, 297, 7258, 4379, 3216,
9474, 8876, 6108, 7814, 9484, 2868, 882, 4206, 3986, 3038, 3659, 3287, 2152, 2964, 7057, 7122, 261, 2716, 4845,
3709, 3562, 1928]
)
for num in range(10002):
ans = check_correctness(nums, num)
if ans != -1:
print(num, nums[check_correctness(nums, num)])
The driver function ran without any assert errors. This proves the correctness of the above two functions.
Commented version in typescript. Based on this answer but modified to return less than or equal to.
/**
* Binary Search of a sorted array but returns the closest smaller value if the
* needle is not in the array.
*
* Returns null if the needle is not in the array and no smaller value is in
* the array.
*
* #param haystack the sorted array to search #param needle the need to search
* for in the haystack #param compareFn classical comparison function, return
* -1 if a is less than b, 0 if a is equal to b, and 1 if a is greater than b
*/
export function lessThanOrEqualBinarySearch<T>(
haystack: T[],
needle: T,
compareFn: (a: T, b: T) => number
): T | null {
let lo = 0;
let hi = haystack.length - 1;
let lowestFound: T | null = null;
// iteratively search halves of the array but when we search the larger
// half keep track of the largest value in the smaller half
while (lo <= hi) {
let mid = (hi + lo) >> 1;
let cmp = compareFn(needle, haystack[mid]);
// needle is smaller than middle
// search in the bottom half
if (cmp < 0) {
hi = mid - 1;
continue;
}
// needle is larger than middle
// search in the top half
else if (cmp > 0) {
lo = mid + 1;
lowestFound = haystack[mid];
} else if (cmp === 0) {
return haystack[mid];
}
}
return lowestFound;
}
Here's a PHP version, based on user0815's answer.
Adapted it to take a function, not just an array, and made it more efficient by avoiding evaluation of $mid_idx twice.
function binarySearchLessOrEqual($start_idx, $end_idx, $search_val, $valueFunction)
{
//N.B. If the start index is bigger or equal to the end index, we've reached the end!
if( $start_idx >= $end_idx )
{
return $valueFunction($end_idx) <= $search_val ? $end_idx : -1;
}
$mid_idx = intval($start_idx + ($end_idx - $start_idx) / 2);
if ( $valueFunction($mid_idx) > $search_val ) //If the function is too big, we search in the bottom half
{
return binarySearchLessOrEqual( $start_idx, $mid_idx-1, $search_val, $valueFunction);
}
else //If the function returns less than OR equal, we search in the top half
{
$ret = binarySearchLessOrEqual($mid_idx+1, $end_idx, $search_val, $valueFunction);
//If nothing is suitable, then $mid_idx was actually the best one!
return $ret == -1 ? $mid_idx : $ret;
}
}
Rather than taking an array, it takes a int-indexed function. You could easily adapt it to take an array instead, or simply use it as below:
function indexOfClosestLesser($array, $searchValue)
{
return binarySearchLessOrEqual(
0,
count($array)-1,
$searchValue,
function ($n) use ($array)
{
return $array[$n];
}
);
}
Tested:
$array = [ 10, 20, 30 ];
echo "0: " . indexOfClosestLesser($array, 0) . "<br>"; //-1
echo "5: " . indexOfClosestLesser($array, 5) . "<br>"; //-1
echo "10: " . indexOfClosestLesser($array, 10) . "<br>"; //0
echo "15: " . indexOfClosestLesser($array, 15) . "<br>"; //0
echo "20: " . indexOfClosestLesser($array, 20) . "<br>"; //1
echo "25: " . indexOfClosestLesser($array, 25) . "<br>"; //1
echo "30: " . indexOfClosestLesser($array, 30) . "<br>"; //2
echo "35: " . indexOfClosestLesser($array, 35) . "<br>"; //2
Try using a pair of global variables, then reference those variables inside the COMPARE function for bsearch
In RPGIV we can call c functions.
The compare function with global variables looks like this:
dcl-proc compInvHdr;
dcl-pi compInvHdr int(10);
elmPtr1 pointer value;
elmPtr2 pointer value;
end-pi;
dcl-ds elm1 based(elmPtr1) likeds(invHdr_t);
dcl-ds elm2 based(elmPtr2) likeds(elm1);
dcl-s low int(10) inz(-1);
dcl-s high int(10) inz(1);
dcl-s equal int(10) inz(0);
select;
when elm1.rcd.RECORDNO < elm2.rcd.RECORDNO;
lastHiPtr = elmPtr2;
return low;
when elm1.rcd.RECORDNO > elm2.rcd.RECORDNO;
lastLoPtr = elmPtr2;
return high;
other;
return equal;
endsl;
end-proc;
Remember, that in bsearch the first element is the search key and the second element is the actual storage element in your array/memory, that is why the COMPARE procedure is using elmPtr2;
the call to bsearch looks like this:
// lastLoPtr and LastHiPtr are global variables
// basePtr points to the beginning of the array
lastLoPtr = basePtr;
lastHiPtr = basePtr + ((numRec - 1) * sizRec));
searchKey = 'somevalue';
hitPtr = bsearch(%addr(searchkey)
:basePtr
:numRec
:sizRec
:%PADDR('COMPINVHDR'));
if hitPtr <> *null;
//? not found
hitPtr = lastLoPtr;
else;
//? found
endif;
So if the key is not found then the hitPtr is set to the key of the closest match, effectively archiving a "Less than or Equal key".
If you want the opposite, the next greater key. Then use lastHiPtr to reference the first key greater than the search key.
Note: protect the global variables against race conditions (if applicable).
Wanted to provide a non-binary search way of doing this, in C#. The following finds the closest value to X, without being greater than X, but it can be equal to X. My function also does not need the list to be sorted. It is also theoretically faster than O(n), but only in the event that the exact target number is found, in which case it terminates early and returns the integer.
public static int FindClosest(List<int> numbers, int target)
{
int current = 0;
int difference = Int32.MaxValue;
foreach(int integer in numbers)
{
if(integer == target)
{
return integer;
}
int diff = Math.Abs(target - integer);
if(integer <= target && integer >= current && diff < difference)
{
current = integer;
difference = diff;
}
}
return current;
}
I tested this with the following setup, and it appears to be working flawlessly:
List<int> values = new List<int>() {1,24,32,6,14,9,11,22 };
int target = 21;
int closest = FindClosest(values,target);
Console.WriteLine("Closest: " + closest);
7 years later, I hope to provide some intuition:
If search_val <= arr[mid], we know for the sure that the solution resides in the interval [lo, mid], inclusive. So, we set right=mid (we probably can set right=mid-1 if mid is not included). Note that if search_val < arr[mid], we in fact know that the solution resides in [lo, mid), mid not inclusive. This is because search_val won't fall back on mid and use mid as the closest value <= search value if it is less than arr[mid].
On the other hand, search_val >= arr[mid]. In this case, we know that the solution resides in [mid, hi]. In fact, even if search_val > arr[mid], the solution is still [mid, hi]. This means that we should set left = mid. HOWEVER, in binary search, left is usually always set to mid + 1 to avoid infinite loops. But this means, when the loops at left==right, it is possible we are 1 index over the solution. Thus, we do a check at the very end to return either the left or left-1, that you can see in the other solutions.
Practice Problem: Search a 2D Matrix
Write an efficient algorithm that searches for a value target in an m x n integer matrix 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 the last integer of the
previous row.
The smart solution to this problem is to treat the two-dimensional array as an one-dimensional one and use regular binary search. But I wrote a solution that first locates the correct row. The process of finding the correct row in this problem is basically the same as finding the closest value less than equal to the search value.
Additionally link on binary search: Useful Insights into Binary Search
a non-recursive way using loop, I'm using this in javascript so I'll just post in javascript:
let left = 0
let right = array.length
let mid = 0
while (left < right) {
mid = Math.floor((left + right) / 2)
if (searchValue < array[mid]) {
right = mid
} else {
left = mid + 1
}
}
return left - 1
since general guideline tells us to look at the middle pointer, many fail to see that the actual answer is the left pointer's final value.
how to reverse a number?
Example1: x = 123, return 321
Example2: x = -123, return -321
this is my answer:
public int reverse(int x) {
int result = 0;
while(x != 0){
result = result * 10 + x % 10;
x = x / 10;
}
return result;
}
but when I input 1534236469 , it will output 1056389759 , this is wrong. what do you think about my program? thanks.
One reason your program cannot give the right answer is that you
store result in an int but you expect to be able to
reverse the number 1534236469.
The correct answer would be 9646324351,
but that number is greater than the largest possible value of an int
so you end up with something else.
Try long long or try using input with no more than 9 digits.
Followup:
I suggested long long because that will fairly reliably give you
an 8-byte integer. You may also get 8 bytes in a long, depending on
where you are building your code,
but Visual C++ on 32-bit Windows (for example) will
give you only 4 bytes. Possibly the 4-byte long will go the way of the 2-byte int soon enough, but at this point in time some of us still have to deal with it.
Jason,
You should just change the type from int to long.
public long reverse(long x)
{
long result = 0;
while (x != 0)
{
result = result * 10 + x % 10;
x = x / 10;
}
return result;
}
You can write x >0 (doesn't matter though )also after that you have to consider negative numbers , I made that change to your logic as follows (Also use long long to avoid overflow):
long long reverse(long long x)
{
int sign = 1;
long long ans=0;
if(x < 0)
sign = -1;
x = abs(x);
while(x > 0)
{
ans *= 10;
ans += x%10;
x /=10;
}
return ans*sign;
}
How about convert to string and reverse? Quite simple:
int reverseDigits(int x) {
String s = Integer.toString(x);
for (int i = 0; i < s.length() / 2; i++) {
char t = s[i];
s[i] = s[s.length() - i - 1];
s[s.length() - i - 1] = t;
}
return Integer.parseInteger(s); // subject to overflow
}
can use long type to store the result
public int reverse(int x) {
long result = 0;
while (x != 0) {
result = result * 10 + x % 10;
x /= 10;
}
if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE)
return 0;
return (int)result;
}
This is a question posted on Leetcode and it gives a wrong answer expecting a 0. The clue is that before returning the reversed integer we have to check if it does not exceed the limit of a 32-bit int ie 2^31-1.
Code in Python 3:
class Solution:
def reverse(self, x: int) -> int:
s=[]
rev=0
neg=False
if x==0:
return 0
if x<0:
x=x* -1
neg=True
while x:
s.append(x%10)
x=int(x/10)
i=len(s)
j=0
while i:
rev=rev+s[j]*10**(i-1)
i=i-1
j=j+1
if(rev>2**31-1):
return 0
return rev * -1 if neg else rev
You are using int for storing the number whereas number is out of range of int. You have tagged algorithm in this question. So, better way would be by using link list. You can google more about it. There are lot of algorithms for reversing a link list.
Why not simply do:
while (x)
print x%10
x /= 10
with a double sign conversion if the value of x is originally negative, to avoid the question of what mod a -ve number is.
A shorter version of Schultz9999's answer:
int reverseDigits(int x) {
String s = Integer.toString(x);
s=new StringBuilder(s).reverse().toString();
return Integer.parseInt(s);
}
Here is the python code of reverse number::
n=int(input('Enter the number:'))
r=0
while (n!=0):
remainder=n%10
r=remainder+(r*10)
n=n//10
print('Reverse order is %d'%r)
A compact Python solution is
reverse = int(str(number)[::-1])
If negative numbers are a possibility, then
num = abs(number) # absolute value of the number
rev = int(str(num)[::-1]) # reverse the number
reverse = -rev # negate the reverse
In JS I wrote it in this way
function reverseNumber(n) {
const reversed = n
.toString()
.split('')
.reverse()
.join('');
return parseInt(reversed) * Math.sign(n);
}
Reverse Integer In JavaScript | Accepted LeetCode solution | Memory efficient
If reversing the number causes the value to go outside the signed 32-bit integer range [-2^31, 2^31 - 1], then returned 0.
Intuition:
First converted the integer to a string which is much easy to reverse and check characters.
Approach:
Converted number to string.
Checked for 1st character negative value.
Spliced (-) and stored if any which is concat in the last.
Then reversed the string without (-).
var reverse = function(x) {
x= x.toString();
let s = Number(x[0]) ? '' : x[0],reverse='';
if(s) { //If x= -123 && here s='-'
x =x.substring(1) // removing '-' from the string
}
for(let i = x.length-1; i>=0; i--) {
if((Number(x[i]) && !reverse) || reverse){
reverse += x[i];
}
}
if(Number(s+reverse) > 2147483648 || (Number(s+reverse) < -2147483648 && Number(s+reverse) < 0)){
return 0
}
return Number(s+reverse); // s='-' or ''
};
I have a sorted array which is rotated n times, n is unknown.Now I want to search an element using binary search in O(nlog n).I implemented the following code, it works fine.
But I think condition if((end-start)==1 ) can be skipped by making some modifications,
can any one suggest?
Eg of array 1 2 3 4 5
2 3 4 5 1 //rotated once
Code:
public static int srch(int a[],int start,int end,int key){
if(start>end)
return -1;
if((end-start)==1 ){
if(key==a[start])
return start;
else if(key==a[end])
return end;
else
return -1;
}
int mid = (start+end)/2;
if(a[mid]== key){
return mid;
}
else{
if(a[start] < a[mid] ){
//first half is sorted
if(key>a[mid]|| key <a[start]){
start= mid+1;
}else{
end =mid-1;
}
}else{
//second half is sorted
if(key>a[mid]){
start= mid+1;
}else{
end =mid-1;
}
}
return srch(a, start, end, key);
}
}
Any better/simple/more efficient solution?
Your solution fails for array {4,5,1,2,3} and key=4.
I think a modification in second part will solve the problem
else{
//second half is sorted
if(key>a[mid] && key<=a[end]){// modified condition
start= mid+1;
}else{
end =mid-1;
}
But I think condition
if((end-start)==1 ) can be skipped by
making some modifications, can any one
suggest?
I suppose this condition is not required at all.
Can u suggest a test case which fails for your modified code.
public static int srch(int a[],int start,int end,int key){
if(start>end)
return -1;
int mid = (start+end)/2;
if(a[mid]== key){
return mid;
}
else{
if(a[start] < a[mid] ){
//first half is sorted
if(key>a[mid]|| key <a[start]){
start= mid+1;
}else{
end =mid-1;
}
}else{
//second half is sorted
if(key>a[mid] && key<=a[high]){
start= mid+1;
}else{
end =mid-1;
}
}
return srch(a, start, end, key);
}
}
Your solution is running in O(log n), so there cannot be a more efficient solution. Maybe parts of your code could be optimized, but that will not effect the running time in terms of O. As you said, the code works and returns the correct values, therefore I'd say it's the correct answer for your interview question.
I haven't checked your code thoroughly for correctness, but your solution is O(log n). You cannot have a better solution algorithmically.