Finding multiple entries with binary search - algorithm

I use standard binary search to quickly return a single object in a sorted list (with respect to a sortable property).
Now I need to modify the search so that ALL matching list entries are returned. How should I best do this?

Well, as the list is sorted, all the entries you are interested in are contiguous. This means you need to find the first item equal to the found item, looking backwards from the index which was produced by the binary search. And the same about last item.
You can simply go backwards from the found index, but this way the solution may be as slow as O(n) if there are a lot of items equal to the found one. So you should better use exponential search: double your jumps as you find more equal items. This way your whole search is still O(log n).

First let's recall the naive binary search code snippet:
int bin_search(int arr[], int key, int low, int high)
{
if (low > high)
return -1;
int mid = low + ((high - low) >> 1);
if (arr[mid] == key) return mid;
if (arr[mid] > key)
return bin_search(arr, key, low, mid - 1);
else
return bin_search(arr, key, mid + 1, high);
}
Quoted from Prof.Skiena:
Suppose we delete the equality test if (s[middle] == key)
return(middle); from the implementation above and return the index low
instead of −1 on each unsuccessful search. All searches will now be
unsuccessful, since there is no equality test. The search will proceed
to the right half whenever the key is compared to an identical array
element, eventually terminating at the right boundary. Repeating the
search after reversing the direction of the binary comparison will
lead us to the left boundary. Each search takes O(lgn) time, so we can
count the occurrences in logarithmic time regardless of the size of
the block.
So, we need two rounds of binary_search to find the lower_bound (find the first number no less than the KEY) and the upper_bound (find the first number bigger than the KEY).
int lower_bound(int arr[], int key, int low, int high)
{
if (low > high)
//return -1;
return low;
int mid = low + ((high - low) >> 1);
//if (arr[mid] == key) return mid;
//Attention here, we go left for lower_bound when meeting equal values
if (arr[mid] >= key)
return lower_bound(arr, key, low, mid - 1);
else
return lower_bound(arr, key, mid + 1, high);
}
int upper_bound(int arr[], int key, int low, int high)
{
if (low > high)
//return -1;
return low;
int mid = low + ((high - low) >> 1);
//if (arr[mid] == key) return mid;
//Attention here, we go right for upper_bound when meeting equal values
if (arr[mid] > key)
return upper_bound(arr, key, low, mid - 1);
else
return upper_bound(arr, key, mid + 1, high);
}
Hope it's helpful :)

If I'm following your question, you have a list of objects which, for the purpose of comparison, look like {1,2,2,3,4,5,5,5,6,7,8,8,9}. A normal search for 5 will hit one of objects that compare as 5, but you want to get them all, is that right?
In that case, I'd suggest a standard binary search which, upon landing on a matching element, starts looking left until it stops matching, and then right (from the first match) again until it stops matching.
Be careful that whatever data structure you are using is not overwriting elements that compare to the same!
Alternatively, consider using a structure that stores elements that compare to the same as a bucket in that position.

I would do two binary searches, one looking for the first element comparing >= the value (in C++ terms, lower_bound) and then one searching for the first element comparing > the value (in C++ terms, upper_bound). The elements from lower_bound to just before upper bound are what you are looking for (in terms of java.util.SortedSet, subset(key, key)).
So you need two different slight modifications to the standard binary search: you still probe and use the comparison at the probe to narrow down the area in which the value you are looking for must lie, but now e.g. for lower_bound if you hit equality, all you know is that the element you are looking for (the first equal value) is somewhere between the first element of the range so far and the value you have just probed - you can't return immediately.

Once you found a match with the bsearch, just recursive bsearch both side until no more match
pseudo code :
range search (type *array) {
int index = bsearch(array, 0, array.length-1);
// left
int upperBound = index -1;
int i = upperBound;
do {
upperBound = i;
i = bsearch(array, 0, upperBound);
} while (i != -1)
// right
int lowerBound = index + 1;
int i = lowerBound;
do {
lowerBound = i;
i = bsearch(array, lowerBound, array.length);
} while (i != -1)
return range(lowerBound, UpperBound);
}
No corner cases are covered though. I think this will keep ur complexity to (O(logN)).

This depends on which implementation of the binary search you use:
In Java and .NET, the binary search will give you an arbitrary element; you must search both ways to get the range that you are looking for.
In C++ you can use equal_range method to produce the result that you want in a single call.
To speed up searches in Java and .NET for cases when the equal range is too long for iterating linearly, you can look for a predecessor element and for the successor element, and take values in the middle of the range that you find, exclusive of the ends.
Should this be too slow because of a second binary search, consider writing your own search that looks for both ends at the same time. This may be a bit tedious, but it should run faster.

I'd start by finding the index of a single element given the sortable property (using "normal" binary search) and then start looking to both left-and-right of the element in the list, adding all elements found to meet the search criterion, stopping at one end when an element doesn't meet the criterion or there are no more elements to traverse, and stopping altogether when both the left-and-right ends meet the stop conditions mentioned before.

This code in Java is counting occurences of target value in a sorted array in O(logN) time in one pass. It's easy to modify it to return list of found indexes, just pass in ArrayList.
Idea is to recursively refine e and b bounds until they become lower and upper boundary for contiguous block having target values;
static int countMatching(int[] arr, int b, int e, int target){
int m = (b+e)/2;
if(e-b<2){
int count = 0;
if(arr[b] == target){
count++;
}
if(arr[e] == target && b!=e){
count++;
}
return count;
}
else if(arr[m] > target){
return countMatching(arr,b,m-1, target);
}
else if(arr[m] < target){
return countMatching(arr, m+1, e, target);
}
else {
return countMatching(arr, b, m-1, target) + 1
+ countMatching(arr, m+1, e, target);
}
}

does your binary search return the element, or the index the element is at? Can you get the index?
Since the list is sorted, all matching elements should appear adjacent. If you can get the index of the item returned in the standard search, you just need to search in both directions from that index until you find non-matches.

Here is the solution by Deril Raju (in the answer above), ported to swift:
func bin_search(_ A: inout [Int], first: Int, last: Int, key: Int, searchLow: Bool) -> Int {
var result = -1
var low = first
var high = last
while low <= high {
let mid = (low + high) / 2
if A[mid] < key {
low = mid + 1
} else if A[mid] > key {
high = mid - 1
} else {
result = mid
if searchLow {
high = mid - 1 // go on searching towards left (lower indices)
} else {
low = mid + 1 // go on searching towards right (higher indices)
}
}
}
return result
}
func bin_search_range(_ A: inout [Int], first: Int, last: Int, key: Int) -> (Int, Int) {
let low = bin_search(&A, first: first, last: last, key: key, searchLow: true)
let high = bin_search(&A, first: first, last: last, key: key, searchLow: false)
return (low, high)
}
func test() {
var A = [1, 2, 3, 3, 3, 4, 4, 4, 4, 5]
assert(bin_search(&A, first: 0, last: A.count - 1, key: 3, searchLow: true) == 2)
assert(bin_search(&A, first: 0, last: A.count - 1, key: 3, searchLow: false) == 4)
assert(bin_search_range(&A, first: 0, last: A.count - 1, key: 3) == (2, 4))
assert(bin_search(&A, first: 0, last: A.count - 1, key: 4, searchLow: true) == 5)
assert(bin_search(&A, first: 0, last: A.count - 1, key: 4, searchLow: false) == 8)
assert(bin_search_range(&A, first: 0, last: A.count - 1, key: 4) == (5, 8))
assert(bin_search_range(&A, first: 0, last: A.count - 1, key: 5) == (9, 9))
assert(bin_search_range(&A, first: 0, last: A.count - 1, key: 0) == (-1, -1))
}
test()

Try this. It works amazingly.
working example, Click here
var arr = [1, 1, 2, 3, "a", "a", "a", "b", "c"]; // It should be sorted array.
// if it arr contain more than one keys than it will return an array indexes.
binarySearch(arr, "a", false);
function binarySearch(array, key, caseInsensitive) {
var keyArr = [];
var len = array.length;
var ub = (len - 1);
var p = 0;
var mid = 0;
var lb = p;
key = caseInsensitive && key && typeof key == "string" ? key.toLowerCase() : key;
function isCaseInsensitive(caseInsensitive, element) {
return caseInsensitive && element && typeof element == "string" ? element.toLowerCase() : element;
}
while (lb <= ub) {
mid = parseInt(lb + (ub - lb) / 2, 10);
if (key === isCaseInsensitive(caseInsensitive, array[mid])) {
keyArr.push(mid);
if (keyArr.length > len) {
return keyArr;
} else if (key == isCaseInsensitive(caseInsensitive, array[mid + 1])) {
for (var i = 1; i < len; i++) {
if (key != isCaseInsensitive(caseInsensitive, array[mid + i])) {
break;
} else {
keyArr.push(mid + i);
}
}
}
if (keyArr.length > len) {
return keyArr;
} else if (key == isCaseInsensitive(caseInsensitive, array[mid - 1])) {
for (var i = 1; i < len; i++) {
if (key != isCaseInsensitive(caseInsensitive, array[mid - i])) {
break;
} else {
keyArr.push(mid - i);
}
}
}
return keyArr;
} else if (key > isCaseInsensitive(caseInsensitive, array[mid])) {
lb = mid + 1;
} else {
ub = mid - 1;
}
}
return -1;
}

Very efficient algorithm for this was found recently.
The algorithm has logarithmic time complexity considering both variables (size of input and amount of searched keys). However searched keys has to be sorted as well.
#define MIDDLE(left, right) ((left) + (((right) - (left)) >> 1))
int bs (const int *arr, int left, int right, int key, bool *found)
{
int middle = MIDDLE(left, right);
while (left <= right)
{
if (key < arr[middle])
right = middle - 1;
else if (key == arr[middle]) {
*found = true;
return middle;
}
else
left = middle + 1;
middle = MIDDLE(left, right);
}
*found = false;
/* left points to the position of first bigger element */
return left;
}
static void _mkbs (const int *arr, int arr_l, int arr_r,
const int *keys, int keys_l, int keys_r, int *results)
{
/* end condition */
if (keys_r - keys_l < 0)
return;
int keys_middle = MIDDLE(keys_l, keys_r);
/* throw away half of keys, if the key on keys_middle is out */
if (keys[keys_middle] < arr[arr_l]) {
_mkbs(arr, arr_l, arr_r, keys, keys_middle + 1, keys_r, results);
return;
}
if (keys[keys_middle] > arr[arr_r]) {
_mkbs(arr, arr_l, arr_r, keys, keys_l, keys_middle - 1, results);
return;
}
bool found;
int pos = bs(arr, arr_l, arr_r, keys[keys_middle], &found);
if (found)
results[keys_middle] = pos;
_mkbs(arr, arr_l, pos - 1, keys, keys_l, keys_middle - 1, results);
_mkbs(arr, (found) ? pos + 1 : pos, arr_r, keys, keys_middle + 1, keys_r, results);
}
void mkbs (const int *arr, int N, const int *keys, int M, int *results)
{ _mkbs(arr, 0, N - 1, keys, 0, M - 1, results); }
Here is the implementation in C and a draft paper intended for publication:
https://github.com/juliusmilan/multi_value_binary_search
Can you please share a use case?

You can use the below code for your problem. The main aim here is first to find the lower bound of the key and then to find the upper bound of the same. Later we get the difference of the indices and we get our answer. Rather than having two different functions, we can use a flag which can be used to find the upper bound and lower bound in the same function.
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int bin_search(int a[], int low, int high, int key, bool flag){
long long int mid,result=-1;
while(low<=high){
mid = (low+high)/2;
if(a[mid]<key)
low = mid + 1;
else if(a[mid]>key)
high = mid - 1;
else{
result = mid;
if(flag)
high=mid-1;//Go on searching towards left (lower indices)
else
low=mid+1;//Go on searching towards right (higher indices)
}
}
return result;
}
int main() {
int n,k,ctr,lowind,highind;
cin>>n>>k;
//k being the required number to find for
int a[n];
for(i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
lowind = bin_search(a,0,n-1,k,true);
if(lowind==-1)
ctr=0;
else{
highind = bin_search(a,0,n-1,k,false);
ctr= highind - lowind +1;
}
cout<<ctr<<endl;
return 0;
}

You can do two searches: one for index before the range and one for index after. Because the before and after can repeat itself - use float as "unique" key"
static int[] findFromTo(int[] arr, int key) {
float beforeKey = (float) ((float) key - 0.2);
float afterKey = (float) ((float) key + 0.2);
int left = 0;
int right = arr.length - 1;
for (; left <= right;) {
int mid = left + (right - left) / 2;
float cur = (float) arr[mid];
if (beforeKey < cur)
right = mid - 1;
else
left = mid + 1;
}
leftAfter = 0;
right = arr.length - 1;
for (; leftAfter <= right;) {
int mid = left + (right - leftAfter) / 2;
float cur = (float) arr[mid];
if (afterKey < cur)
right = mid - 1;
else
left = mid + 1;
}
return new int[] { left, leftAfter };
}

You can use recursion to solve the problem. first, call binary_search on the list, if the matching element is found then the left side of the list is called, and the right side of the list is reached. The matching element index is stored in the vector and returns the vector.
vector<int> binary_search(int arr[], int n, int key) {
vector<int> ans;
int st = 0;
int last = n - 1;
helper(arr, st, last, key, ans);
return ans;
}
Recursive function:
void helper(int arr[], int st, int last, int key, vector<int> &ans) {
if (st > last) {
return;
}
while (st <= last) {
int mid = (st + last) / 2;
if (arr[mid] == key) {
ans.push_back(mid);
helper(arr, st, mid - 1, key, ans); // left side call
helper(arr, mid + 1, last, key, ans); // right side call
return;
} else if (arr[mid] > key) {
last = mid - 1;
} else {
st = mid + 1;
}
}
}

Related

Given a bitonic array and element x in the array, find the index of x in 2log(n) time

First, a bitonic array for this question is defined as one such that for some index K in an array of length N where 0 < K < N - 1 and 0 to K is a monotonically increasing sequence of integers, and K to N - 1 is a monotonically decreasing sequence of integers.
Example: [1, 3, 4, 6, 9, 14, 11, 7, 2, -4, -9]. It monotonically increases from 1 to 14, then decreases from 14 to -9.
The precursor to this question is to solve it in 3log(n), which is much easier. One altered binary search to find the index of the max, then two binary searchs for 0 to K and K + 1 to N - 1 respectively.
I presume the solution in 2log(n) requires you solve the problem without finding the index of the max. I've thought about overlapping the binary searches, but beyond that, I'm not sure how to move forward.
The algorithms presented in other answers (this and this) are unfortunately incorrect, they are not O(logN) !
The recursive formula f(L) = f(L/2) + log(L/2) + c doesn't lead to f(L) = O(log(N)) but leads to f(L) = O((log(N))^2) !
Indeed, assume k = log(L), then log(2^(k-1)) + log(2^(k-2)) + ... + log(2^1) = log(2)*(k-1 + k-2 + ... + 1) = O(k^2). Hence, log(L/2) + log(L/4) + ... + log(2) = O((log(L)^2)).
The right way to solve the problem in time ~ 2log(N) is to proceed as follows (assuming the array is first in ascending order and then in descending order):
Take the middle of the array
Compare the middle element with one of its neighbor to see if the max is on the right or on the left
Compare the middle element with the desired value
If the middle element is smaller than the desired value AND the max is on the left side, then do bitonic search on the left subarray (we are sure that the value is not in the right subarray)
If the middle element is smaller than the desired value AND the max is on the right side, then do bitonic search on the right subarray
If the middle element is bigger than the desired value, then do descending binary search on the right subarray and ascending binary search on the left subarray.
In the last case, it might be surprising to do a binary search on a subarray that may be bitonic but it actually works because we know that the elements that are not in the good order are all bigger than the desired value. For instance, doing an ascending binary search for the value 5 in the array [2, 4, 5, 6, 9, 8, 7] will work because 7 and 8 are bigger than the desired value 5.
Here is a fully working implementation (in C++) of the bitonic search in time ~2logN:
#include <iostream>
using namespace std;
const int N = 10;
void descending_binary_search(int (&array) [N], int left, int right, int value)
{
// cout << "descending_binary_search: " << left << " " << right << endl;
// empty interval
if (left == right) {
return;
}
// look at the middle of the interval
int mid = (right+left)/2;
if (array[mid] == value) {
cout << "value found" << endl;
return;
}
// interval is not splittable
if (left+1 == right) {
return;
}
if (value < array[mid]) {
descending_binary_search(array, mid+1, right, value);
}
else {
descending_binary_search(array, left, mid, value);
}
}
void ascending_binary_search(int (&array) [N], int left, int right, int value)
{
// cout << "ascending_binary_search: " << left << " " << right << endl;
// empty interval
if (left == right) {
return;
}
// look at the middle of the interval
int mid = (right+left)/2;
if (array[mid] == value) {
cout << "value found" << endl;
return;
}
// interval is not splittable
if (left+1 == right) {
return;
}
if (value > array[mid]) {
ascending_binary_search(array, mid+1, right, value);
}
else {
ascending_binary_search(array, left, mid, value);
}
}
void bitonic_search(int (&array) [N], int left, int right, int value)
{
// cout << "bitonic_search: " << left << " " << right << endl;
// empty interval
if (left == right) {
return;
}
int mid = (right+left)/2;
if (array[mid] == value) {
cout << "value found" << endl;
return;
}
// not splittable interval
if (left+1 == right) {
return;
}
if(array[mid] > array[mid-1]) {
if (value > array[mid]) {
return bitonic_search(array, mid+1, right, value);
}
else {
ascending_binary_search(array, left, mid, value);
descending_binary_search(array, mid+1, right, value);
}
}
else {
if (value > array[mid]) {
bitonic_search(array, left, mid, value);
}
else {
ascending_binary_search(array, left, mid, value);
descending_binary_search(array, mid+1, right, value);
}
}
}
int main()
{
int array[N] = {2, 3, 5, 7, 9, 11, 13, 4, 1, 0};
int value = 4;
int left = 0;
int right = N;
// print "value found" is the desired value is in the bitonic array
bitonic_search(array, left, right, value);
return 0;
}
The algorithm works recursively by combining bitonic and binary searches:
def bitonic_search (array, value, lo = 0, hi = array.length - 1)
if array[lo] == value then return lo
if array[hi] == value then return hi
mid = (hi + lo) / 2
if array[mid] == value then return mid
if (mid > 0 & array[mid-1] < array[mid])
| (mid < array.length-1 & array[mid+1] > array[mid]) then
# max is to the right of mid
bin = binary_search(array, value, low, mid-1)
if bin != -1 then return bin
return bitonic_search(array, value, mid+1, hi)
else # max is to the left of mid
bin = binary_search(array, value, mid+1, hi)
if bin != -1 then return bin
return bitonic_search(array, value, lo, mid-1)
So the recursive formula for the time is f(l) = f(l/2) + log(l/2) + c where log(l/2) comes from the binary search and c is the cost of the comparisons done in the function body.
Answers those provided have time complexity of (N/2)*logN. Because the worst case may include too many sub-searches which are unnecessary. A modification is to compare the target value with the left and right element of sub series before searching. If target value is not between two ends of the monotonic series or less than both ends of the bitonic series, subsequent search is redundant. This modification leads to 2lgN complexity.
There are 5 main cases depending on where the max element of array is, and whether middle element is greater than desired value
Calculate middle element.
Compare middle element desired value, if it matches search ends. Otherwise proceed to next step.
Compare middle element with neighbors to see if max element is on left or right. If both of the neighbors are less than middle element, then element is not present in the array, hence exit.(Array mentioned in the question will hit this case first as 14, the max element, is in middle)
If middle element is less than desired value and max element is on right, do bitonic search in right subarray
If middle element is less than desired value and max element is on left, do bitonic search in left subarray
If middle element is greater than desired value and max element is on left, do descending binary search in right subarray
If middle element is greater than desired value and max element is on right, do ascending binary search in left subarray
In the worst case we will be doing two comparisons each time array is divided in half, hence complexity will be 2*logN
public int FindLogarithmicGood(int value)
{
int lo = 0;
int hi = _bitonic.Length - 1;
int mid;
while (hi - lo > 1)
{
mid = lo + ((hi - lo) / 2);
if (value < _bitonic[mid])
{
return DownSearch(lo, hi - lo + 1, mid, value);
}
else
{
if (_bitonic[mid] < _bitonic[mid + 1])
lo = mid;
else
hi = mid;
}
}
return _bitonic[hi] == value
? hi
: _bitonic[lo] == value
? lo
: -1;
}
where DownSearch is
public int DownSearch(int index, int count, int mid, int value)
{
int result = BinarySearch(index, mid - index, value);
if (result < 0)
result = BinarySearch(mid, index + count - mid, value, false);
return result;
}
and BinarySearch is
/// <summary>
/// Exactly log(n) on average and worst cases.
/// Note: System.Array.BinarySerch uses 2*log(n) in the worst case.
/// </summary>
/// <returns>array index</returns>
public int BinarySearch(int index, int count, int value, bool asc = true)
{
if (index < 0 || count < 0)
throw new ArgumentOutOfRangeException();
if (_bitonic.Length < index + count)
throw new ArgumentException();
if (count == 0)
return -1;
// "lo minus one" trick
int lo = index - 1;
int hi = index + count - 1;
int mid;
while (hi - lo > 1)
{
mid = lo + ((hi - lo) / 2);
if ((asc && _bitonic[mid] < value) || (!asc && _bitonic[mid] > value))
lo = mid;
else
hi = mid;
}
return _bitonic[hi] == value ? hi : -1;
}
github
Finding the change of sign among the first order differences, by standard dichotomic search, will take 2Lg(n) array accesses.
You can do slightly better by using the search strategy for the maximum of a unimodal function known as Fibonacci search. After n steps each involving a single lookup, you reduce the interval size by a factor Fn, corresponding to about Log n/Log φ ~ 1.44Lg(n) accesses to find the maximum.
This marginal gain makes a little more sense when array accesses are instead costly funciton evaluations.
When it comes to searching Algorithms in O(log N) time, You gotta think of binary search only.
The concept here is to first find the peak point,
for ex: Array = [1 3 5 6 7 12 6 4 2 ] -> Here, 12 is the peak. Once detected and gotta mark as mid, Now simply do a binary search in Array[0:mid] and Array[mid:len(Array)].
Note: The second array from mid -> len is a descending array and need to make a small variation in binary search.
For finding the Bitonic Point :-) [ Written in Python ]
start, end = 0, n-1
while start <= end:
mid = start + end-start//2
if (mid == 0 or arr[mid-1] < arr[mid]) and (mid==n-1 or arr[mid+1] < arr[mid]):
return mid
if mid > 0 and arr[mid-1] > arr[mid]:
end = mid-1
else:
start = mid+1
Once found the index, Do the respective Binary Search. Woola...All done :-)
For a binary split, there are three cases:
max item is at right, then binary search left, and bitoinc search right.
max item is at left, then binary search right, and bitoinc search left.
max item is at the split point exactly, then binary both left and right.
caution: the binary search used in left and right are different because of increasing/decreasing order.
public static int bitonicSearch(int[] a, int lo, int hi, int key) {
int mid = (lo + hi) / 2;
int now = a[mid];
if (now == key)
return mid;
// deal with edge cases
int left = (mid == 0)? a[mid] : a[mid - 1];
int right = (mid == a.length-1)? a[mid] : a[mid + 1];
int leftResult, rightResult;
if (left < now && now < right) { // max item is at right
leftResult = binarySearchIncreasing(a, lo, mid - 1, key);
if (leftResult != -1)
return leftResult;
return bitonicSearch(a, mid + 1, hi, key);
}
else if (left > now && now > right) { // max item is at left
rightResult = binarySearchDecreasing(a, mid + 1, hi, key);
if (rightResult != -1)
return rightResult;
return bitonicSearch(a, lo, mid - 1, key);
}
else { // max item stands at the split point exactly
leftResult = binarySearchIncreasing(a, lo, mid - 1, key);
if (leftResult != -1)
return leftResult;
return binarySearchDecreasing(a, mid + 1, hi, key);
}
}

Find the first "missing" number in a sorted list

Let's say I have the continuous range of integers [0, 1, 2, 4, 6], in which the 3 is the first "missing" number. I need an algorithm to find this first "hole". Since the range is very large (containing perhaps 2^32 entries), efficiency is important. The range of numbers is stored on disk; space efficiency is also a main concern.
What's the best time and space efficient algorithm?
Use binary search. If a range of numbers has no hole, then the difference between the end and start of the range will also be the number of entries in the range.
You can therefore begin with the entire list of numbers, and chop off either the first or second half based on whether the first half has a gap. Eventually you will come to a range with two entries with a hole in the middle.
The time complexity of this is O(log N). Contrast to a linear scan, whose worst case is O(N).
Based on the approach suggested by #phs above, here is the C code to do that:
#include <stdio.h>
int find_missing_number(int arr[], int len) {
int first, middle, last;
first = 0;
last = len - 1;
middle = (first + last)/2;
while (first < last) {
if ((arr[middle] - arr[first]) != (middle - first)) {
/* there is a hole in the first half */
if ((middle - first) == 1 && (arr[middle] - arr[first] > 1)) {
return (arr[middle] - 1);
}
last = middle;
} else if ((arr[last] - arr[middle]) != (last - middle)) {
/* there is a hole in the second half */
if ((last - middle) == 1 && (arr[last] - arr[middle] > 1)) {
return (arr[middle] + 1);
}
first = middle;
} else {
/* there is no hole */
return -1;
}
middle = (first + last)/2;
}
/* there is no hole */
return -1;
}
int main() {
int arr[] = {3, 5, 1};
printf("%d", find_missing_number(arr, sizeof arr/(sizeof arr[0]))); /* prints 4 */
return 0;
}
Since numbers from 0 to n - 1 are sorted in an array, the first numbers should be same as their indexes. That's to say, the number 0 is located at the cell with index 0, the number 1 is located at the cell with index 1, and so on. If the missing number is denoted as m. Numbers less then m are located at cells with indexes same as values.
The number m + 1 is located at a cell with index m, The number m + 2 is located at a cell with index m + 1, and so on. We can see that, the missing number m is the first cell whose value is not identical to its value.
Therefore, it is required to search in an array to find the first cell whose value is not identical to its value. Since the array is sorted, we could find it in O(lg n) time based on the binary search algorithm as implemented below:
int getOnceNumber_sorted(int[] numbers)
{
int length = numbers.length
int left = 0;
int right = length - 1;
while(left <= right)
{
int middle = (right + left) >> 1;
if(numbers[middle] != middle)
{
if(middle == 0 || numbers[middle - 1] == middle - 1)
return middle;
right = middle - 1;
}
else
left = middle + 1;
}
return -1;
}
This solution is borrowed from my blog: http://codercareer.blogspot.com/2013/02/no-37-missing-number-in-array.html.
Based on algorithm provided by #phs
int findFirstMissing(int array[], int start , int end){
if(end<=start+1){
return start+1;
}
else{
int mid = start + (end-start)/2;
if((array[mid] - array[start]) != (mid-start))
return findFirstMissing(array, start, mid);
else
return findFirstMissing(array, mid+1, end);
}
}
Below is my solution, which I believe is simple and avoids an excess number of confusing if-statements. It also works when you don't start at 0 or have negative numbers involved! The complexity is O(lg(n)) time with O(1) space, assuming the client owns the array of numbers (otherwise it's O(n)).
The Algorithm in C Code
int missingNumber(int a[], int size) {
int lo = 0;
int hi = size - 1;
// TODO: Use this if we need to ensure we start at 0!
//if(a[0] != 0) { return 0; }
// All elements present? If so, return next largest number.
if((hi-lo) == (a[hi]-a[lo])) { return a[hi]+1; }
// While 2 or more elements to left to consider...
while((hi-lo) >= 2) {
int mid = (lo + hi) / 2;
if((mid-lo) != (a[mid]-a[lo])) { // Explore left-hand side
hi = mid;
} else { // Explore right hand side
lo = mid + 1;
}
}
// Return missing value from the two candidates remaining...
return (lo == (a[lo]-a[0])) ? hi + a[0] : lo + a[0];
}
Test Outputs
int a[] = {0}; // Returns: 1
int a[] = {1}; // Returns: 2
int a[] = {0, 1}; // Returns: 2
int a[] = {1, 2}; // Returns: 3
int a[] = {0, 2}; // Returns: 1
int a[] = {0, 2, 3, 4}; // Returns: 1
int a[] = {0, 1, 2, 4}; // Returns: 3
int a[] = {0, 1, 2, 4, 5, 6, 7, 8, 9}; // Returns: 3
int a[] = {2, 3, 5, 6, 7, 8, 9}; // Returns: 4
int a[] = {2, 3, 4, 5, 6, 8, 9}; // Returns: 7
int a[] = {-3, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // Returns: -1
int a[] = {-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // Returns: 10
The general procedure is:
(Optional) Check if the array starts at 0. If it doesn't, return 0 as missing.
Check if the array of integers is complete with no missing integer. If it is not missing an integer, return the next largest integer.
In a binary search fashion, check for a mismatch between the difference in the indices and array values. A mismatch tells us which half a missing element is in. If there is a mismatch in the first half, move left, otherwise move right. Do this until you have two candidate elements left to consider.
Return the number that is missing based on incorrect candidate.
Note, the algorithm's assumptions are:
First and last elements are considered to never be missing. These elements establish a range.
Only one integer is ever missing in the array. This will not find more than one missing integer!
Integer in the array are expected to increase in steps of 1, not at any other rate.
Have you considered a run-length encoding? That is, you encode the first number as well as the count of numbers that follow it consecutively. Not only can you represent the numbers used very efficiently this way, the first hole will be at the end of the first run-length encoded segment.
To illustrate with your example:
[0, 1, 2, 4, 6]
Would be encoded as:
[0:3, 4:1, 6:1]
Where x:y means there is a set of numbers consecutively starting at x for y numbers in a row. This tells us immediately that the first gap is at location 3. Note, however, that this will be much more efficient when the assigned addresses are clustered together, not randomly dispersed throughout the range.
if the list is sorted, I'd iterate over the list and do something like this Python code:
missing = []
check = 0
for n in numbers:
if n > check:
# all the numbers in [check, n) were not present
missing += range(check, n)
check = n + 1
# now we account for any missing numbers after the last element of numbers
if check < MAX:
missing += range(check, MAX + 1)
if lots of numbers are missing, you might want to use #Nathan's run-length encoding suggestion for the missing list.
Missing
Number=(1/2)(n)(n+1)-(Sum of all elements in the array)
Here n is the size of array+1.
Array: [1,2,3,4,5,6,8,9]
Index: [0,1,2,3,4,5,6,7]
int findMissingEmementIndex(int a[], int start, int end)
{
int mid = (start + end)/2;
if( Math.abs(a[mid] - a[start]) != Math.abs(mid - start) ){
if( Math.abs(mid - start) == 1 && Math.abs(a[mid] - a[start])!=1 ){
return start +1;
}
else{
return findMissingElmementIndex(a,start,mid);
}
}
else if( a[mid] - a[end] != end - start){
if( Math.abs(end - mid) ==1 && Math.abs(a[end] - a[mid])!=1 ){
return mid +1;
}
else{
return findMissingElmementIndex(a,mid,end);
}
}
else{
return No_Problem;
}
}
This is an interview Question. We will have an array of more than one missing numbers and we will put all those missing numbers in an ArrayList.
public class Test4 {
public static void main(String[] args) {
int[] a = { 1, 3, 5, 7, 10 };
List<Integer> list = new ArrayList<>();
int start = 0;
for (int i = 0; i < a.length; i++) {
int ch = a[i];
if (start == ch) {
start++;
} else {
list.add(start);
start++;
i--; // a must do.
} // else
} // for
System.out.println(list);
}
}
Functional Programming solution (Scala)
Nice and elegant
Lazy evaluation
def gapFinder(sortedList: List[Int], start: Int = 0): Int = {
def withGuards: Stream[Int] =
(start - 1) +: sortedList.toStream :+ (sortedList.last + 2)
if (sortedList.isEmpty) start
else withGuards.sliding(2)
.dropWhile { p => p.head + 1 >= p.last }.next()
.headOption.getOrElse(start) + 1
} // 8-line solution
// Tests
assert(gapFinder(List()) == 0)
assert(gapFinder(List[Int](0)) == 1)
assert(gapFinder(List[Int](1)) == 0)
assert(gapFinder(List[Int](2)) == 0)
assert(gapFinder(List[Int](0, 1, 2)) == 3)
assert(gapFinder(List[Int](0, 2, 4)) == 1)
assert(gapFinder(List[Int](0, 1, 2, 4)) == 3)
assert(gapFinder(List[Int](0, 1, 2, 4, 5)) == 3)
import java.util.Scanner;
class MissingNumber {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int[] arr =new int[n];
for (int i=0;i<n;i++){
arr[i]=scan.nextInt();
}
for (int i=0;i<n;i++){
if(arr[i+1]==arr[i]+1){
}
else{
System.out.println(arr[i]+1);
break;
}
}
}
}
I was looking for a super simple way to find the first missing number in a sorted array with a max potential value in javascript and didn't have to worry about efficiency too much as I didn't plan on using a list longer 10-20 items at the most. This is the recursive function I came up with:
function findFirstMissingNumber(sortedList, index, x, maxAllowedValue){
if(sortedList[index] == x && x < maxAllowedValue){
return findFirstMissingNumber(sortedList, (index+1), (x+1), maxAllowedValue);
}else{ return x; }
}
findFirstMissingNumber([3, 4, 5, 7, 8, 9], 0, 3, 10);
//expected output: 6
Give it your array, the index you wish to start at, the value you expect it to be and the maximum value you'd like to check up to.
i got one algorithm for finding the missing number in the sorted list. its complexity is logN.
public int execute2(int[] array) {
int diff = Math.min(array[1]-array[0], array[2]-array[1]);
int min = 0, max = arr.length-1;
boolean missingNum = true;
while(min<max) {
int mid = (min + max) >>> 1;
int leftDiff = array[mid] - array[min];
if(leftDiff > diff * (mid - min)) {
if(mid-min == 1)
return (array[mid] + array[min])/2;
max = mid;
missingNum = false;
continue;
}
int rightDiff = array[max] - array[mid];
if(rightDiff > diff * (max - mid)) {
if(max-mid == 1)
return (array[max] + array[mid])/2;
min = mid;
missingNum = false;
continue;
}
if(missingNum)
break;
}
return -1;
}
Based on algorithm provided by #phs
public class Solution {
public int missing(int[] array) {
// write your solution here
if(array == null){
return -1;
}
if (array.length == 0) {
return 1;
}
int left = 0;
int right = array.length -1;
while (left < right - 1) {
int mid = left + (right - left) / 2;
if (array[mid] - array[left] != mid - left) { //there is gap in [left, mid]
right = mid;
}else if (array[right] - array[mid] != right - mid) { //there is gap in [mid, right]
left = mid;
}else{ //there is no gapin [left, right], which means the missing num is the at 0 and N
return array[0] == 1 ? array.length + 1 : 1 ;
}
}
if (array[right] - array[left] == 2){ //missing number is between array[left] and array[right]
return left + 2;
}else{
return array[0] == 1 ? -1 : 1; //when ther is only one element in array
}
}
}
public static int findFirst(int[] arr) {
int l = -1;
int r = arr.length;
while (r - l > 1) {
int middle = (r + l) / 2;
if (arr[middle] > middle) {
r = middle;
}
l = middle;
}
return r;
}

Find smallest number in Sorted Rotatable Array

I came across this question in one Interview. Please help me in getting the solution.
Question is:
You have sorted rotatable array, i. e. the array contains elements which are sorted and it can be rotated circularly, like if the elements in array are [5,6,10,19,20,29] then rotating first time array becomes [29,5,6,10,19,20] and on second time it becomes [20,29,5,6,10,19] and so on.
So you need to find the smallest element in the array at any point. You won’t be provided with number times array is rotated. Just given the rotated array elements and find out the smallest among them. In this case output should be 5.
Method 1:
You can do this in O(logN) time.
Use a modified binary search to find the point of rotation which is an index i such that arr[i] > arr[i+1].
Example:
[6,7,8,9,1,2,3,4,5]
^
i
The two sub-arrays (arr[1], arr[2], .., arr[i]) and (arr[i+1], arr[i+2], ..., arr[n]) are sorted.
The answer is min(arr[1], arr[i+1])
Method 2:
When you split the sorted, rotated array into two halves (arr[1],..,arr[mid]) and (arr[mid+1],..,arr[n]), one of them is always sorted and the other always has the min. We can directly use a modified binary search to keep searching in the unsorted half
// index of first element
l = 0
// index of last element.
h = arr.length - 1
// always restrict the search to the unsorted
// sub-array. The min is always there.
while (arr[l] > arr[h]) {
// find mid.
mid = (l + h)/2
// decide which sub-array to continue with.
if (arr[mid] > arr[h]) {
l = mid + 1
} else {
h = mid
}
}
// answer
return arr[l]
The above algorihtm fails if data element is repeated like {8,8,8,8,8} or {1,8,8,8,8} or {8,1,8,8,8} or {8,8,1,8,8} or {8,8,8,8,1}
// solution pasted below will work all test cases :)
//break the array in two subarray and search for pattern like a[mid]>a[mid+1]
// and return the min position
public static int smallestSearch(int[] array,int start,int end)
{
if(start==end)
return array.length;
int mid=(start+end)/2;
if(array[mid]>array[mid+1])
return min(mid+1,smallestSearch(array,start,mid),smallestSearch(array,mid+1,end));
else
return min(smallestSearch(array,start,mid),smallestSearch(array,mid+1,end));
}
public static int min(int a,int b)
{
if(a==b)
return a;
else if(a<b)
return a;
else
return b;
}
public static int min(int a,int b,int c)
{
if(a<c)
{
if(a<b)
{
return a;
}
else
{
return b;
}
}
else
{
if(b<c)
return b;
else
return c;
}
}
To Find the smallest number in the sorted rotated array:
using Binary search concept
public class RotatedSortedArrayWithoutDuplicates1 {
public static void main(String[] args) {
int[] a = { 4, 6, 8, 10, 34, 56, 78, 1, 3 };
System.out.println(findMin(a));
}
private static int findMin(int[] a) {
if (a.length == 0 || a == null) {
return -1;
}
int start = 0;
int last = a.length - 1;
while (start + 1 < last) {
int mid = start + (last - start) / 2;
int m = a[mid];
int s = a[start];
int l = a[last];
if (m > l) {
start = mid + 1;
}
if (m < l) {
last = mid;
} else {
last--;
}
} // while
if (a[start] > a[last]) {
return a[last];
} else {
return a[start];
}
}
}
But if you don't want to use Binary Search, then :
public class Abc {
public static void main(String[] args) {
int[] a = { 4, 5, 6, 7, 7, 8, 9, 1, 1, 2, 3, 3 };
System.out.println(findMin(a));
}
public static int findMin(int[] a) {
int min = a[a.length - 1];
for (int i = 0; i < a.length; i++) {
if (min > a[i]) {
min = a[i];
break;
}
}
return min;
}// findmin
}// end
Here is the code in Python:
def fix(a):
min = a[0]
for i in range(len(a)):
if(min > a[i]):
min = a[i]
break
return min
a = [2, 2,3,4,1,2]
print(fix(a))
My code is below with the algorithm as comments. Works even for the repeated elements.
//Find Min in Rotated Sorted Array
//Example: int array[10] = {7, 8, 9, 10, 11, 12, 3, 4, 5, 6};
// Min in the above array is 3
// Solution: Recursively search (Modified binary search) for the Pivot where is the smallest Element is present
// Algorithm:
// 1) Find the Mid of the Array
// 2) call the recursive function on segment of array in which there is a deviation in the order
// If (A[low] > A[mid]) array segment in which deviation in the order present is (low, mid)
// If (A[low] < A[mid]) array segment in which deviation in the order present is (mid + 1, high)
// Time Complexity: O(logn)
// Space Complexity: is of the recursive function stack that is being used
#define MIN(x,y) (x) <= (y) ? (x): (y)
int MininRotatedSortedArray(int A[], int low, int high)
{
if(low > high)
return -1;
if(low == high - 1)
return MIN(A[low], A[high]);
int mid = low + (high - low)/2;
if(A[low] > A[mid])
return MininRotatedSortedArray(A, low, mid);
else if(A[low] < A[mid])
return MininRotatedSortedArray(A, mid + 1, high);
else
return A[mid];
}
This can be done in O(1) time best case, O(n) time worst case, and O(lg n) time on average.
For a rotated sorted array, if the first element in the array is less than the last element in the array, then the sorted array is not rotated (or rotated 0 position). The minimum element is simply the first element.
If the middle element is less than the last element, then the minimum element is in [first, middle].
If the middle element is greater than the last element, then the minimum element is in [middle + 1, last].
If the middle element is equal to the last element, then there are two sub-cases:
the first element is larger than the last element, in which case the minimum element is in [first, middle + 1];
the first element is equal to the last element, in which case it is inconclusive to reject either half of the array. Reduce to linear search. For example, for arrays such as [5,5,5,1,5] and [5,1,5,5,5], it is impossible by just examining the first, last and middle element (since they are all equal) which half of the array the minimum element lies.
I wrote the following code in C++ to solve this problem, which should handle all cases (empty array, repeated elements).
template <typename Iterator>
Iterator rotated_min(Iterator begin, Iterator end)
{
while (begin != end)
{
if (*begin < *(end - 1))
{
return begin;
}
Iterator mid = begin + (end - 1 - begin) / 2;
if (*mid < *(end - 1))
{
end = mid + 1;
}
else if (*mid > *(end - 1))
{
begin = mid + 1;
}
else
{
if (*begin > *(end - 1))
{
end = mid + 1;
++begin;
}
else
{
//reduce to linear search
typename ::std::iterator_traits<Iterator>::value_type min_value = *begin;
Iterator min_element = begin;
for (Iterator i = begin + 1; i != end; ++i)
{
if (*i < min_value)
{
min_value = *i;
min_element = i;
}
}
return min_element;
}
}
}
return begin;
}
Find Min index in circular sorted array
Example : [7,8,9,1,2,3,4,5,6]
int findMinIndex(int []a, int start, int end)
{
int mid = (start + end)/2;
if (start - end == 1)
if(a[start] < a[end])
return start;
else
return end;
if (a[mid] > a[end]){
return findMinIndex(a,mid,end);
}
else{
return findMinIndex(a,start,mid);
}
return -1; //Not found
}
In case any one needs it.. My implementation in java..
takes care of sorted/unsorted ascending//descending order usecases..
drawback is it will still perform log n steps to find min value in a perfectly sorted set with no rotation.
http://ideone.com/fork/G3zMIb
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
int [] a = {3,3,0,2,2,2,2,1,2,2,2,2,2,2,2,2,2};
System.out.println(recursiveSplit(a,0,a.length-1));
}
public static int findMin(int x, int y){
if(x<=y){
return x;
}else{
return y;
}
}
public static int recursiveSplit(int[] arr , int a , int b){
int mid = (int) Math.floor(a + (b-a)/2);
int h1_l = a;
int h1_u = mid;
int h2_l = mid+1;
int h2_u = b;
int x=0;
int y=0;
//single element
if(a==b){
return arr[a];
}
//adjacent positions
if(h1_u-h1_l==1){
x=findMin(arr[h1_u],arr[h1_l]);
}else{
//else split
x=recursiveSplit(arr,h1_l,h1_u);
}
if(h2_u-h2_l==1){
y=findMin(arr[h2_u],arr[h2_l]);
}else{
y=recursiveSplit(arr, h2_l,h2_u);
}
return findMin(x, y);
}
}
Errors/suggestions/failed usecases are welcomed
public int findMin(int[] num) {
return findMin(num, 0, num.length-1);
}
public int findMin(int[] num, int left, int right){
if(left==right) return num[left];
if(left+1==right) return Math.min(num[left], num[right]);
int mid = (left+right)/2;
if(num[mid]>num[right]){
return findMin(num,mid+1,right);
}else if(num[mid]<num[right]){
return findMin(num,left,mid);
}else{
if(num[mid]==num[left]){
return Math.min(findMin(num,left,mid), findMin(num,mid,right));
}else{
return findMin(num,left,mid);
}
}
}
The following algorithm takes log(n) time. Assuming the array has no duplicate.
public int findMin(int[] num) {
if(num.length == 0) return -1
int r = num.length-1, l = 0;
while(l<r){
if(num[l]<=num[r]) return num[l]; //when not rotated, return the left most value
int mid = (r+l)/2;
if(num[mid]<num[r]){
r = mid;
}else{
l = mid+1;
}
}
return num[l];
}
I did it using a slightly modified version of binary search. What I am doing here is I keep going left or right based on where the minimum could be. For example in an ascending array if the mid element is less than the left most element, its possible that the minimum is to the left. While recursing thru the array, I also keep track of the minimum. The recursion continues until the end and then the latest min is returned. This also works with repeated elements.
public static void main(String[] args) throws IOException {
int[] rotated = {6, 7, 8, 1, 2, 3, 4, 5};
int min = findMin(rotated);
System.out.println(min);//1
}
public static int findMin(int[] sorted) {
return findMinRecursively(sorted, sorted[0], 0, (sorted.length - 1));
}
private static int findMinRecursively(int[] sorted, int min, int leftIndex, int rightIndex) {
if (leftIndex > rightIndex) {
return min;
}
int midIndex = (leftIndex + rightIndex) / 2;
if (sorted[midIndex] < min) {
min = sorted[midIndex];
}
if (sorted[midIndex] < sorted[leftIndex]) {
return findMinRecursively(sorted, min, leftIndex, (midIndex - 1));
} else {
return findMinRecursively(sorted, min, (midIndex + 1), rightIndex);
}
}
Question : Find minimum in a sorted rotated array .
Solution 1 : Using Binary Search
class Test18 {
public static void main(String[] args) {
int[] a = { 5, 6, 7, 8, 9, 10, 1, 2, 3 };
System.out.println(findmin(a));
}
// find min in a sorted rotated array
private static int findmin(int[] a) {
int start = 0;
int last = a.length - 1;
while (start + 1 < last) {
int mid = start + (last - start) / 2;
if (a[mid] > a[last]) {
start = mid + 1;
}
if (a[mid] < a[last]) {
last = mid;
} else {
mid--;
}
} // while
if (a[start] > a[last]) {
return a[last];
} else {
return a[start];
}
}
}
def searchinrotatedarray(arr1,l,h):
if l>h:
return arr1[0]
if h==l:
return arr1[l]
mid=(l+h)//2
if mid<h and arr1[mid+1]<arr1[mid]:
return arr1[mid+1]
elif mid>l and arr1[mid-1]<arr1[mid]:
return arr1[mid]
elif arr1[mid]<arr1[h]:
return searchinrotatedarray(arr1,l,mid-1)
else:
return searchinrotatedarray(arr1,mid+1,h)
first if statement checks if even array is rotated at all. in that case first element is the min . if length of list is 1 then that element is min.
else if mid element is less than last element then continue to look in second half else look for the element in first half
//java program to find minimum element in a sorted array rotated
//about any pivot in O(log n) in worst case and O(1) in best case
class ArrayRotateMinimum {
public static void main(String str[]) {
// initialize with your sorted rotated array here
int array[] = { 9, 1, 2, 3, 4, 5, 6, 7, 8, };
System.out.println("Minimum element is: " + minimumElement(array));
}
static int minimumElement(int array[]) {
// variables to keep track of low and high indices
int low, mid, high;
// initializing variables with appropriate values
low = 0;
high = array.length - 1;
while (low < high) {
// mid is always defined to be the average of low and high
mid = (low + high) / 2;
if (array[low] > array[mid]) {
// for eg if array is of the form [9,1,2,4,5],
// then shift high to mid to reduce array size by half
// while keeping minimum element between low and high
high = mid;
} else if (array[mid] > array[high]) {
// this condition deals with the end case when the final two
// elements in the array are of the form [9,1] during the
// last iteration of the while loop
if (low == mid) {
return array[high];
}
// for eg if array is of the form [4,5,9,1,2],
// then shift low to mid to reduce array size by half
// while keeping minimum element between low and high
low = mid;
} else {
// the array has not been rotated at all
// hence the first element happens to be the smallest element
return array[low];
}
}
//return first element in case array size is just 1
return array[0];
}
}
This is my pythonic solution using recursion:
Time complexity is O(log(n)) & Space complexity: O(1)
class Solution(object):
def findMin(self, nums):
left = 0
right = len(nums) -1
mid = len(nums) // 2
if len(nums) == 0:
return -1
if len(nums) == 1:
return nums[left]
if len(nums) == 2:
return min(nums[left], nums[right])
if nums[left] < nums[right]:
return nums[left]
elif nums[mid] > nums[left]:
return self.findMin(nums[mid + 1: ])
elif nums[mid] < nums[left]:
return self.findMin(nums[: mid + 1])
Here is a very simple answer, it will work for all test cases:
int a[] = {5,6,7,1,2,3,4};
int a[] = {1,2,3};
int a[] = {3,2,1};
int a[] = {3,1,2};
int a[] = {2,2,2,2};
public class FindSmallestNumberInSortedRotatedArray {
public static void main(String[] args) {
int a[] = { 4, 5, 6, 7, 1, 2, 3 };
int j = a.length - 1;
int i = 0;
while (i < j) {
int m = (i + j) / 2;
if (a[m] < a[m + 1] && a[m] < a[m - 1]) {
System.out.println(a[m] + "is smallest element ");
break;
} else if (a[m] > a[m + 1] && a[m - 1] > a[m + 1]) {
i = m + 1;
} else {
j = m - 1;
}
}
if (i == j)
System.out.println(a[i] + " is smallest element");
}
Solution for both array with duplicate and not, with the recursive binary search approach.
Unique array
var min = (A, l, h) => {
if(l >= h) return A[l];
let m = Math.floor((l + h) / 2);
// as its unique
if(A[m] > A[h]) {
// go towards right as last item is small than mid
return min(A, m + 1, h);
} else if(A[m] > A[m - 1]) {
// go towards left as prev item is smaller than current
return min(A, l, m - 1);
} else {
// right and left is greater than current
return A[m];
}
}
/**
* #param {number[]} nums
* #return {number}
*/
var findMin = function(nums) {
// If array is rotated nums.length time or same as it is
if(nums[0] < nums[nums.length - 1]) return nums[0];
return min(nums, 0, nums.length - 1);
};
Array with duplicates
var min = (A, l, h) => {
if(l >= h) return A[l];
// traverse from left "and right" to avoid duplicates in the end
while(A[l] == A[l+1]) {
l++;
}
let m = Math.floor((l + h) / 2);
// as its unique
if(A[m] > A[h]) {
// go towards right as last item is small than mid
return min(A, m + 1, h);
} else if(A[m] >= A[m - 1]) {
// go towards left as prev item is smaller than current
return min(A, l, m - 1);
} else {
// right and left is greater than current
return A[m];
}
}
/**
* #param {number[]} nums
* #return {number}
*/
var findMin = function(nums) {
// If array is rotated nums.length time or same as it is
if(nums[0] < nums[nums.length - 1]) return nums[0];
return min(nums, 0, nums.length - 1);
};

Searching a number in a rotated sorted Array

Given a Sorted Array which can be rotated find an Element in it in minimum Time Complexity.
eg : Array contents can be [8, 1, 2, 3, 4, 5]. Assume you search 8 in it.
The solution still works out to a binary search in the sense that you'll need to partition the array into two parts to be examined.
In a sorted array, you just look at each part and determine whether the element lives in the first part (let's call this A) or the second part (B). Since, by the definition of a sorted array, partitions A and B will be sorted, this requires no more than some simple comparisons of the partition bounds and your search key.
In a rotated sorted array, only one of A and B can be guaranteed to be sorted. If the element lies within a part which is sorted, then the solution is simple: just perform the search as if you were doing a normal binary search. If, however, you must search an unsorted part, then just recursively call your search function on the non-sorted part.
This ends up giving on a time complexity of O(lg n).
(Realistically, I would think that such a data structure would have a index accompanying it to indicate how many positions the array has been rotated.)
Edit: A search on Google takes me to this somewhat dated (but correct) topic on CodeGuru discussing the same problem. To add to my answer, I will copy some pseudocode that was given there so that it appears here with my solution (the thinking follows the same lines):
Search(set):
if size of set is 1 and set[0] == item
return info on set[0]
divide the set into parts A and B
if A is sorted and the item is in the A's range
return Search(A)
if B is sorted and the item is in the B's range
return Search(B)
if A is not sorted
return Search(A)
if B is not sorted
return Search(B)
return "not found"
O(log(N))
Reduced to the problem of finding the largest number position, which can be done by checking the first and last and middle number of the area, recursively reduce the area, divide and conquer, This is O(log(N)) no larger than the binary search O(log(N)).
EDIT:
For example, you have
6 7 8 1 2 3 4 5
^ ^ ^
By looking at the 3 numbers you know the location of the smallest/largest numbers (will be called mark later on) is in the area of 6 7 8 1 2, so 3 4 5 is out of consideration (usually done by moving your area start/end index(int) pointing to the number 6 and 2 ).
Next step,
6 7 8 1 2
^ ^ ^
Once again you will get enough information to tell which side (left or right) the mark is, then the area is reduced to half again (to 6 7 8).
This is the idea: I think you can refine a better version of this, actually, for an interview, an OK algorithm with a clean piece of codes are better than the best algorithm with OK codes: you 'd better hand-on some to heat-up.
Good luck!
I was asked this question in an interview recently.The question was describe an algorithm to search a "key" in a circular sorted array.I was also asked to write the code for the same.
This is what I came up with:
Use divide and conquer binary search.
For each subarray check if the array is sorted. If sorted use classic binary search
e.g
data[start]< data[end] implies that the data is sorted. user binary
else
divide the array further till we get sorted array.
public boolean search(int start,int end){
int mid =(start+end)/2;
if(start>end)
{
return false;
}
if(data[start]<data[end]){
return this.normalBinarySearch(start, end);
}
else{
//the other part is unsorted.
return (this.search(start,mid) ||
this.search(mid+1,end));
}
}
where normalBinarySearch is a simple binary search.
It a simple modification of normal binary search. In fact we it will work for both rotated and sorted arrays. In the case of sorted arrays it will end up doing more work than it really needs to however.
For a rotated array, when you split the array into two subarrays, it is possible one of those subarrays will not be in order. You can easily check if if each half is sorted by comparing the first and last value in the subarray.
Knowing whether each subarray is sorted or not, we can make a choice of what do do next.
1) left subarray is sorted, and the value is within the range of the left subarray (check both ends!)
Then search recursively search left subarray.
2) right subarray is sorted, and the value is within the range of the right subarray (check both ends!)
Then recursively search right subarray.
3) left is Not sorted
Then recursively search left subarray
4) Right is Not sorted
Then recursively search right subarray.
Note: the difference between this and a normal binary search is that we cannot simply choose the subarray to recurse on by simply comparing the last value left subarray (of first value of the right subarray) to make our decision. The value has to be strictly in the left or right subarray and that subarray has to sorted, otherwise we must recurse on the unsorted subarray.
Here is some Objective-C that implements this:
#implementation BinarySearcher
- (BOOL)isValue:(int)value inArray:(int[])array withArraySize:(int)size {
return [self subSearchArray:array forValue:value fromIndex:0 toIndex:size -1];
}
- (BOOL)subSearchArray:(int[])array forValue:(int)value fromIndex:(int)left toIndex:(int)right {
if (left <= right) {
int middle = (left + right) / 2;
BOOL leftArraySorted = array[left] <= array[middle];
BOOL rightArraySorted = array[middle + 1] <= array[right];
if (array[middle] == value) {
return YES;
} else if (leftArraySorted && value >= array[left] && value < array[middle]) {
return [self subSearchArray:array forValue:value fromIndex:left toIndex:middle];
} else if (rightArraySorted && value >= array[middle + 1] && value <= array[right]) {
return [self subSearchArray:array forValue:value fromIndex:middle + 1 toIndex:right];
} else if (!leftArraySorted) {
return [self subSearchArray:array forValue:value fromIndex:left toIndex:middle];
} else if (!rightArraySorted) {
return [self subSearchArray:array forValue:value fromIndex:middle + 1 toIndex:right];
}
}
return NO;
}
#end
At any index, one partition will be sorted and other unsorted. If key lies within sorted partition, search within sorted array, else in non sorted partition.
BS(lo, hi)
m = (lo + hi)/2
if(k = a[m])
return m
b = 0
if(a[hi] > a[m])
b = 1
if(b)
if(k > a[m] && k<a[hi])
BS(m+1, hi)
else
BS(lo, m-1)
Here is my approach at it:
public static int findMin(int[] a, int start, int end){
int mid = (start + end)/2;
if(start == mid){
return a[mid+1];
}else if(a[start] > a[mid]){
return findMin(a, start, mid);
}else if(a[mid+1] > a[start]){
return findMin(a, mid+1, end);
}else{
return a[mid+1];
}
}
Time complexity: O(log n)
You can wrap an array with a class that only exposes
E get(int index);
and would behave as regular sorted array.
For ex if you have 4 5 1 2 3 4, wrapper.get(0) will return 1.
Now you can just reuse binary search solution.
Wrapper can look like that:
class RotatedArrayWrapper<T> {
int startIndex;
private final List<T> rotatedArray;
public RotatedArrayWrapper(List<T> rotatedArray) {
this.rotatedArray = rotatedArray;
//find index of the smalest element in array
//keep in mind that there might be duplicates
startIndex = ...
}
public T get(int index) {
int size = rotatedArray.size();
if (index > size) throw Exception...
int actualIndex = (startIndex + index) % size;
return rotatedArray.get(actualIndex);
}
}
Python implementation. Could use to be more pythonic:
from bisect import bisect_left
def index(a, x):
"""Binary search to locate the leftmost value exactly equal to x.
see http://docs.python.org/2/library/bisect.html#searching-sorted-lists
>>> index([5, 14, 27, 40, 51, 70], 27)
2
>>> index([1, 2, 3, 4], 10)
Traceback (most recent call last):
...
ValueError
"""
i = bisect_left(a, x)
if i != len(a) and a[i] == x:
return i
raise ValueError
def _index_shifted(value, sequence, start, stop):
"""Recursive reset location and binary search"""
# if at reset (min) and it's not the value, it's not there
if start == stop and sequence[start] != value:
return -1
mid = (stop + start) // 2
# check mid, since we are already here
if sequence[mid] == value:
return mid
# right side is sorted
elif sequence[mid] < sequence[stop]:
# if value falls in range, search righ
if sequence[stop] >= value > sequence[mid]:
return index(sequence[mid:stop + 1], value) + mid
# partition left side
return _index_shifted(value, sequence, start, mid)
# left side is sorted
else:
# if value falls in range, search left
if sequence[mid] > value >= sequence[start]:
return index(sequence[start:mid], value) + start
# partition right side
return _index_shifted(value, sequence, mid + 1, stop)
def index_shifted(sequence, value):
"""Returns index of value in a shifted sorted sequence; -1 if not present.
>>> index_shifted([10, 13, 16, 19, 22, 25, 28, 31, 34, 37], 10)
0
>>> index_shifted([10, 13, 16, 19, 22, 25, 28, 31, 34, 37], 37)
9
>>> index_shifted([34, 37, 10, 13, 16, 19, 22, 25, 28, 31], 10)
2
>>> index_shifted([34, 37, 10, 13, 16, 19, 22, 25, 28, 31], 37)
1
>>> index_shifted([34, 37, 10, 13, 16, 19, 22, 25, 28, 31], 13)
3
>>> index_shifted([34, 37, 10, 13, 16, 19, 22, 25, 28, 31], 25)
7
>>> index_shifted([25, 28, 31, 34, 37, 10, 13, 16, 19, 22], 10)
5
>>> index_shifted([25, 28, 31, 34, 37, 10, 13, 16, 19, 22], -10)
-1
>>> index_shifted([25, 28, 31, 34, 37, 10, 13, 16, 19, 22], 100)
-1
"""
return _index_shifted(value, sequence, 0, len(sequence) - 1)
My solution:
efficiency: O(logn)
public static int SearchRotatedSortedArray(int l, int d, int[] array, int toFind) {
if (l >= d) {
return -1;
}
if (array[l] == toFind) {
return l;
}
if (array[d] == toFind) {
return d;
}
int mid = (l + d) / 2;
if (array[mid] == toFind) {
return mid;
}
if ((array[mid] > toFind && toFind > array[l]) || (array[mid] < toFind && array[d] < toFind)) {
return SearchRotatedSortedArray(l, mid - 1, array, toFind);
} else {
return SearchRotatedSortedArray(mid + 1, d, array, toFind);
}
}
//this solution divides the array in two equal subarrays using recurssion and apply binary search on individual sorted array and it goes on dividing unsorted array
public class SearchRotatedSortedArray
{
public static void main(String... args)
{
int[] array={5,6,1,2,3,4};
System.out.println(search(array,Integer.parseInt(args[0]),0,5));
}
public static boolean search(int[] array,int element,int start,int end)
{
if(start>=end)
{
if (array[end]==element) return true;else return false;
}
int mid=(start+end)/2;
if(array[start]<array[end])
{
return binarySearch(array,element,start,end);
}
return search(array,element,start,mid)||search(array,element,mid+1,end);
}
public static boolean binarySearch(int[] array,int element,int start,int end)
{
int mid;
while(start<=end)
{
mid=(start+end)/2;
if(array[mid]==element)
return true;
if(array[mid]<element)
{
start=mid+1;
}
else
{
end=mid-1;
}
}
return false;
}
}
int findIndexInRotatedSort( vector<int> input, int s, int e, int toFind )
{
if (s > e || s >= input.size() || e < 0)
{
return -1;
}
int m = (s + e)/2;
int sVal = input.at(s);
int eVal = input.at(e);
int mVal = input.at(m);
if (sVal == toFind)
return s;
if (eVal == toFind)
return e;
if (mVal == toFind)
return m;
bool isFirstOrdered = (sVal < mVal);
bool isSecondOrdered = (mVal < eVal);
if (toFind > mVal)
{
if (!isSecondOrdered || toFind < eVal)
{
return findIndexInRotatedSort( input, m+1, e, toFind );
}
else
{
return findIndexInRotatedSort( input, s, m-1, toFind );
}
}
else
{
if (!isFirstOrdered || toFind > sVal)
{
return findIndexInRotatedSort( input, s, m-1, toFind );
}
else
{
return findIndexInRotatedSort( input, m+1, e, toFind );
}
}
}
public class RoatatedSorted {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] rotArray = {5,6,7,8,9,10,15,16,17,1,2,3,4,};
search(rotArray,0,rotArray.length-1,10);
}
private static void search(int[] a, int low, int high,int key) {
//int mid = low + (high-low)/2;
//if(a[mid]==a[key]){System.out.println("element found at" + key+1 +" position"); return;}
// find pos to split array
int pos = findSplitIndex(a,low,high);
System.out.println("split pos found at" + pos +" position");
if(key>=a[low]&& key <=a[pos])
bsearch(a,low,pos,key);
if(key>=a[pos+1]&& key <=a[high])
bsearch(a,pos+1,high,key);
}
private static void bsearch(int[] a, int low, int high,int key) {
// TODO Auto-generated method stub
if(low>high) return;
int mid = low + (high-low)/2;
if(a[mid]==key)
{System.out.println("element found at" + ++mid +" position"); return;}
if(a[mid] > key)
bsearch(a,low,mid-1,key);
if(a[mid]<key)
bsearch(a,mid+1,high,key);
}
private static int findSplitIndex(int[] a, int low, int high) {
// TODO Auto-generated method stub
int mid;
if(low>high)return -1;
while(true) {
mid = low + (high-low)/2;
if( a[mid]>a[mid+1])
break;
if(a[mid]>a[low])
low=mid;
if(a[high]>a[mid])
high=mid;
}
return mid;
}
}
First to find the Minimum element in the array then divide array in two part. After that search the given value using Binary search tree. Complexity : O(logn)
If you have to find the Minimum element in the rotated Array, use same approach,just skip Binary search. Complexity : O(logn)
//Search an element in a sorted and pivoted array
class SearchInPivotedSortedArray
{
//searchInOrtedPivotedArray : Return index of matched element with given value.
public static int searchInSortedPivotedArray(int[] A, int value)
{
int min = findMinElement(A,0,A.Length-1);
if (min == A[0])
return binarySearchTree(A, 0, A.Length-1, value);
if (value <= A[A.Length-1])
return binarySearchTree(A, min, A.Length-1, value);
else
return binarySearchTree(A, 0, min-1, value);
}
//return index of Pivot element
public static int findMinElement(int[] Array, int low, int high)
{
if (low >= high)
return low;
int mid = (low + high) / 2;
if (mid > low && Array[mid] < Array[mid - 1])
return mid;
if (mid < high && Array[mid] > Array[mid + 1])
return mid + 1;
if (Array[mid] < Array[high])
return findMinElement(Array, low, mid - 1);
return findMinElement(Array, mid + 1, high);
}
//Return match element index, if not found return -1
public static int binarySearchTree(int[] array, int low, int high,int value)
{
if (low > high)
return -1;
int mid = (low + high)/2;
if (array[mid] == value)
return mid;
if (array[mid] > value)
return binarySearchTree(array, low, mid - 1, value);
else
return binarySearchTree(array, mid + 1, high, value);
}
}
this is a O(logn) solution: tested. it works on both sorted and rotated sorted arrays:
public static int rbs(int[] a, int l, int r, int t) {
if (a[l] <= a[r]) {
return bs(a, l, r, t);
}
if (r < l) {
return -1;
} else {
int m = (l+r) / 2;
if (a[m] == t) {
return m;
} else if (a[m] > t) { // check left half
if (a[l] > a[m]) { // left is unsorted
return rbs(a, l, m-1, t);
} else { // left is sorted
if (a[l] < t) { // t is in range
return bs(a, l, m-1, t);
} else if (a[l] > t) { // t is out of range on left
if (a[r] >= t) {
return rbs (a, m+1, r, t);
} else
return -1;
} else
return l;
}
} else { // other side
if (a[r] < a[m]) { // right is unsorted
return rbs(a, m+1, r, t);
} else { // right is sorted
if (a[r] > t) { // t is in range
return bs(a, m+1, r, t);
} else if (a[r] < t) { // t is out of range on right side
if (a[l] <= t) {
return rbs (a, l, m-1, t);
} else
return -1;
} else
return r;
}
}
}
}
public static int bs(int[] a, int l, int r, int t) {
int m = (l+r) / 2;
if (r < l) {
return -1;
} else {
if (a[m] == t)
return m;
else if (a[m] < t)
return bs(a, m+1, r, t);
else
return bs (a, l, m-1, t);
}
}
Try out this solution,
public static int findElement(int[] a, int key, int left, int right) {
if (left > right) {
return -1;
}
int mid = (left + right) / 2;
if (key == a[mid]) {
return mid;
} else if (key < a[mid]) {
return (a[left] <= a[mid] && a[left] < key ? findElement(
a, key, left, mid - 1) : findElement(a, key,
mid + 1, right));
} else {
return (a[mid] <= a[right] && a[right] < key ? findElement(
a, key, left, mid - 1) : findElement(a, key,
mid + 1, right));
}
}
Here is a C++ implementation of #Andrew Song's answer
int search(int A[], int s, int e, int k) {
if (s <= e) {
int m = s + (e - s)/2;
if (A[m] == k)
return m;
if (A[m] < A[e] && k > A[m] && k <= A[e])
return search(A, m+1, e, k);
if (A[m] > A[s] && k < A[m] && k >= A[s])
return search(A, s, m-1, k);
if (A[m] < A[s])
return search(A, s, m-1, k);
if (A[m] > A[e])
return search(A, m+1, e, k);
}
return -1;
}
This is 100% working and tested solution in PYTHON
Program to find a number from a sorted but rotated array
def findNumber(a, x, start, end):
if start > end:
return -1
mid = (start + end) / 2
if a[mid] == x:
return mid
## Case : 1 if a[start] to a[mid] is sorted , then search first half of array
if a[start] < a[mid]:
if (x >= a[start] and x <= a[mid]):
return findNumber(a, x, start, mid - 1)
else:
return findNumber(a,x, mid + 1, end)
## Case: 2 if a[start] to a[mid] is not sorted , then a[mid] to a[end] mist be sorted
else:
if (x >= a[mid] and x <= a[end]):
return findNumber(a, x, mid + 1, end)
else:
return findNumber(a,x, start, mid -1)
a = [4,5,6,7,0,1,2]
print "Your array is : " , a
x = input("Enter any number to find in array : ")
result = findNumber(a, x, 0, len(a) - 1)
print "The element is present at %d position: ", result
In worst case you have to use linear search and examine whole array to find a target, because, unlike a set, an array may contain duplicates. And if an array contains duplicates you can't use binary search in the given problem.
If queries on particular array are infrequent you can use standard binary search if whole array is sorted (first element is strictly smaller than last element) and use linear search otherwise. For more information see How fast can you make linear search? discussion on StackOverflow and 10 Optimizations on Linear Search article by Thomas A. Limoncelli.
Hovewer, if queries are frequent you can sort input array in linear time (see Fastest algorithm for circle shift N sized array for M position discussion on StackOverflow) in preprocessing step and use standard binary search as usual.
#include<iostream>
using namespace std;
int BinarySearch(int *a,int key, int length)
{
int l=0,r=length-1,res=-1;
while(l<=r)
{
int mid = (l+r)/2;
if(a[mid] == key) {res = mid; break;}
//Check the part of the array that maintains sort sequence and update index
// accordingly.
if((a[mid] < a[r] && ( key > a[mid] && key <=a[r]))
|| a[mid] > a[r] && !( key>=a[l] && key <a[mid]))
{
l = mid+1;
}
else r = mid-1;
}
return res;
}
void main()
{
int arr[10] = {6,7,8,9,10,13,15,18,2,3};
int key = 8;
cout<<"Binary Search Output: "<<BinarySearch(arr,key,10);
}
Find element index in rotated sorted array
Example : [6,7,8,1,2,3,5]
int findElementIndex(int []a, int element, int start, int end)
{
int mid = (start + end)>>1;
if(start>end)
return -1;
if(a[mid] == element)
return mid;
if(a[mid] < a[start])
{
if(element <= a[end] && element > a[mid])
{
return findElementIndex(a,element,mid+1,end);
}
else{
return findElementIndex(a,element,start,mid-1);
}
}
else if(a[mid] > a[start]){
if(element >= a[start] && element < a[mid])
return findElementIndex(a,element,start,mid-1);
else
return findElementIndex(a,element,mid+1,end);
}
else if (a[mid] == a[start]){
if(a[mid] != a[end]) // repeated elements
return findElementIndex(a,element,mid+1,end);
else
int left = findElementIndex(a,element,start,mid-1);
int right = findElementIndex(a,element,mid+1,end);
return (left != -1) ? left : right;
}
}

Given an array of numbers, find out if 3 of them add up to 0

Given an array of numbers, find out if 3 of them add up to 0.
Do it in N^2, how would one do this?
O(n^2) solution without hash tables (because using hash tables is cheating :P). Here's the pseudocode:
Sort the array // O(nlogn)
for each i from 1 to len(array) - 1
iter = i + 1
rev_iter = len(array) - 1
while iter < rev_iter
tmp = array[iter] + array[rev_iter] + array[i]
if tmp > 0
rev_iter--
else if tmp < 0
iter++
else
return true
return false
Basically using a sorted array, for each number (target) in an array, you use two pointers, one starting from the front and one starting from the back of the array, check if the sum of the elements pointed to by the pointers is >, < or == to the target, and advance the pointers accordingly or return true if the target is found.
Not for credit or anything, but here is my python version of Charles Ma's solution. Very cool.
def find_sum_to_zero(arr):
arr = sorted(arr)
for i, target in enumerate(arr):
lower, upper = 0, len(arr)-1
while lower < i < upper:
tmp = target + arr[lower] + arr[upper]
if tmp > 0:
upper -= 1
elif tmp < 0:
lower += 1
else:
yield arr[lower], target, arr[upper]
lower += 1
upper -= 1
if __name__ == '__main__':
# Get a list of random integers with no duplicates
from random import randint
arr = list(set(randint(-200, 200) for _ in range(50)))
for s in find_sum_to_zero(arr):
print s
Much later:
def find_sum_to_zero(arr):
limits = 0, len(arr) - 1
arr = sorted(arr)
for i, target in enumerate(arr):
lower, upper = limits
while lower < i < upper:
values = (arr[lower], target, arr[upper])
tmp = sum(values)
if not tmp:
yield values
lower += tmp <= 0
upper -= tmp >= 0
put the negative of each number into a hash table or some other constant time lookup data structure. (n)
loop through the array getting each set of two numbers (n^2), and see if their sum is in the hash table.
First sort the array, then for each negative number (A) in the array, find two elements in the array adding up to -A. Finding 2 elements in a sorted array that add up to the given number takes O(n) time, so the entire time complexity is O(n^2).
C++ implementation based on the pseudocode provided by Charles Ma, for anyone interested.
#include <iostream>
using namespace std;
void merge(int originalArray[], int low, int high, int sizeOfOriginalArray){
// Step 4: Merge sorted halves into an auxiliary array
int aux[sizeOfOriginalArray];
int auxArrayIndex, left, right, mid;
auxArrayIndex = low;
mid = (low + high)/2;
right = mid + 1;
left = low;
// choose the smaller of the two values "pointed to" by left, right
// copy that value into auxArray[auxArrayIndex]
// increment either left or right as appropriate
// increment auxArrayIndex
while ((left <= mid) && (right <= high)) {
if (originalArray[left] <= originalArray[right]) {
aux[auxArrayIndex] = originalArray[left];
left++;
auxArrayIndex++;
}else{
aux[auxArrayIndex] = originalArray[right];
right++;
auxArrayIndex++;
}
}
// here when one of the two sorted halves has "run out" of values, but
// there are still some in the other half; copy all the remaining values
// to auxArray
// Note: only 1 of the next 2 loops will actually execute
while (left <= mid) {
aux[auxArrayIndex] = originalArray[left];
left++;
auxArrayIndex++;
}
while (right <= high) {
aux[auxArrayIndex] = originalArray[right];
right++;
auxArrayIndex++;
}
// all values are in auxArray; copy them back into originalArray
int index = low;
while (index <= high) {
originalArray[index] = aux[index];
index++;
}
}
void mergeSortArray(int originalArray[], int low, int high){
int sizeOfOriginalArray = high + 1;
// base case
if (low >= high) {
return;
}
// Step 1: Find the middle of the array (conceptually, divide it in half)
int mid = (low + high)/2;
// Steps 2 and 3: Recursively sort the 2 halves of origianlArray and then merge those
mergeSortArray(originalArray, low, mid);
mergeSortArray(originalArray, mid + 1, high);
merge(originalArray, low, high, sizeOfOriginalArray);
}
//O(n^2) solution without hash tables
//Basically using a sorted array, for each number in an array, you use two pointers, one starting from the number and one starting from the end of the array, check if the sum of the three elements pointed to by the pointers (and the current number) is >, < or == to the targetSum, and advance the pointers accordingly or return true if the targetSum is found.
bool is3SumPossible(int originalArray[], int targetSum, int sizeOfOriginalArray){
int high = sizeOfOriginalArray - 1;
mergeSortArray(originalArray, 0, high);
int temp;
for (int k = 0; k < sizeOfOriginalArray; k++) {
for (int i = k, j = sizeOfOriginalArray-1; i <= j; ) {
temp = originalArray[k] + originalArray[i] + originalArray[j];
if (temp == targetSum) {
return true;
}else if (temp < targetSum){
i++;
}else if (temp > targetSum){
j--;
}
}
}
return false;
}
int main()
{
int arr[] = {2, -5, 10, 9, 8, 7, 3};
int size = sizeof(arr)/sizeof(int);
int targetSum = 5;
//3Sum possible?
bool ans = is3SumPossible(arr, targetSum, size); //size of the array passed as a function parameter because the array itself is passed as a pointer. Hence, it is cummbersome to calculate the size of the array inside is3SumPossible()
if (ans) {
cout<<"Possible";
}else{
cout<<"Not possible";
}
return 0;
}
This is my approach using Swift 3 in N^2 log N...
let integers = [-50,-40, 10, 30, 40, 50, -20, -10, 0, 5]
First step, sort array
let sortedArray = integers.sorted()
second, implement a binary search method that returns an index like so...
func find(value: Int, in array: [Int]) -> Int {
var leftIndex = 0
var rightIndex = array.count - 1
while leftIndex <= rightIndex {
let middleIndex = (leftIndex + rightIndex) / 2
let middleValue = array[middleIndex]
if middleValue == value {
return middleIndex
}
if value < middleValue {
rightIndex = middleIndex - 1
}
if value > middleValue {
leftIndex = middleIndex + 1
}
}
return 0
}
Finally, implement a method that keeps track of each time a set of "triplets" sum 0...
func getTimesTripleSumEqualZero(in integers: [Int]) -> Int {
let n = integers.count
var count = 0
//loop the array twice N^2
for i in 0..<n {
for j in (i + 1)..<n {
//Sum the first pair and assign it as a negative value
let twoSum = -(integers[i] + integers[j])
// perform a binary search log N
// it will return the index of the give number
let index = find(value: twoSum, in: integers)
//to avoid duplications we need to do this check by checking the items at correspondingly indexes
if (integers[i] < integers[j] && integers[j] < integers[index]) {
print("\([integers[i], integers[j], integers[index]])")
count += 1
}
}
}
return count
}
print("count:", findTripleSumEqualZeroBinary(in: sortedArray))
prints--- count: 7
void findTriplets(int arr[], int n)
{
bool found = false;
for (int i=0; i<n-1; i++)
{
unordered_set<int> s;
for (int j=i+1; j<n; j++)
{
int x = -(arr[i] + arr[j]);
if (s.find(x) != s.end())
{
printf("%d %d %d\n", x, arr[i], arr[j]);
found = true;
}
else
s.insert(arr[j]);
}
}
if (found == false)
cout << " No Triplet Found" << endl;
}

Resources