Google Interview Question
Software Engineer / DevelopersCountry: United States
Interview Type: In-Person
This approach wouldn't work in following case
10 -20 8 7 6 5 4 3 2 1
The problem with it is that if triplet around mid is decreasing, we still need to recurse into both halves, to make sure there were no "break" there (see the case above). And it makes complexity linear in worst case.
The question could be worded better, but the idea I think is that the numbers exclusively decrease until a certain point where they exclusively increase. There is only one such point in the array. We need to find that point, and we need to do it in better than O(n) time.
So lets use binary search. Cut the array into two parts. For the first half, check the last two elements. Is it still decreasing? if so, forget that half. recursively search in the second half.
When you find the increasing part, keep that half and resursively search it.
Eventually you should find the point where it goes from decreasing to increasing, and this will take logn time.
The difficult is that the questions states greater than/equal, and not just greater than. So its possible to have 9, 8, 5, 4, 3, 3, 3, 3, 3 as an input value, and the algorithm proposed above will end without finding the spot where it starts increasing. however, the spot that you found should still be the center point of a valid return triplet.
All we need is to check left and right adjacent elements of the mid. Pseudo-code:
IF start > end
return -1;
mid = (end - start) / 2
IF ar[mid-1] >= ar[mid] && ar[mid] <= ar[mid+1]
found triplet -> return [mid-1,mid,mid+1]
ELSE IF ar[mid-1] > ar[mid+1]
decreasing sequence -> go right
ELSE
increasing sequence -> go left
I think the code will crash if mid ends up being 0 or ar.length-1.
The two ways that this method should return -1 is if the numbers are only increasing, or only decreasing. In one case, the search should end when we hit index 0, and in the other case, the search should end when we hit index length-1.
We need something like:
if (mid <= 0 || mid >= ar.length-1){
return 0;
*O(log n) time complexity*
A = [9, 8, 5, 4, 3, 2, 1, 7]
def findTriplet():
first = 0
last = len(A) - 1
while (True):
mid = int((first + last) / 2)
if (A[mid] <= A[mid - 1]) and (A[mid] <= A[mid + 1]):
print(str(A[mid-1]) + " " + str(A[mid]) + " " + str(A[mid+1]))
return
if A[mid] > A[mid + 1]:
first = mid + 1
if A[mid] > A[mid - 1]:
last = mid - 1
findTriplet()
public void printTriplet(int[] array) {
if(array == null || array.length == 0) {
System.err.println("Empty array");
return ;
}
int index = getTriplet(array, 0, array.length -1 );
if(index == -1) {
System.out.println("No such triplet found");
return;
}
System.out.println("The required triplet is " +
array[index-1] + ", " +
array[index] + ", " +
array[index + 1]);
}
public int getTriplet(int[] array, int lower, int upper) {
if(lower >= upper) return -1;
int middle = lower + (upper - lower)/2;
if(array[middle - 1] >= array[middle] && array[middle + 1] >= array[middle])
return middle;
int index = getTriplet(array, lower, middle);
if(index != -1) return index;
index = getTriplet(array, middle + 1, upper);
if(index != -1) return index;
return -1;
}
agree with GeekTycoon.. idea is gud but it does hav O(n) time cplxty since it scans both side
The time complexity is not O(n). Suppose the input array is 4,3,2,6,5. Then according to program mid=0+(4-0)/2, then mid is 2 and arr[mid]=2 then here we can get our condition true and thus return the mid so how is it traversing the whole array..?? Remember this is binary search whenever it finds the mid with the given condition it returns. Also you should first check for binary search in wiki and there you should check under the tag recursion
public static void findTriplet(int lower, int array[]){
while(lower<array.length-2){
if(array[lower]>=array[lower+1]&&array[lower+1]<=array[lower+2]){
System.out.println("Triplet is "+array[lower]+" "+array[lower+1]+" "+array[lower+2]);
return;
}
lower+=2;
}
findTriplet(1,array);
}
public static void main(String[] args){
int[]array= {9, 8, 6, 7};
findTriplet(0,array);
}
}
public class findTriplet {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int arr[]={9, 8, 5, 4, 3, 2, 1, 7};
int n=arr.length;
int i=findTriplet(arr,0,n-1);
if(i==-1)
{
System.out.println("No triplet exists");
}
else
{
System.out.println("Triplet exists and it is \n");
System.out.println(arr[i-1]+" "+arr[i]+" "+arr[i+1]);
}
}
public static int findTriplet(int arr[], int low, int high) {
while (low <= high) {
int mid = (low + high) / 2;
if(mid-1<0||mid+1>high)
{
break;
}
if (arr[mid-1]>=arr[mid]&&arr[mid]<=arr[mid+1]) {
return mid;
} else if (arr[mid-1] < arr[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
}
change
else if (arr[mid-1] < arr[mid]) {
high = mid - 1;
} else {
low = mid + 1;
} to
else if (arr[mid-1] < arr[mid]) {
high = mid;
} else {
low = mid;
Binary search - just need to decide to which side to recurse, based on values of the neighbors. Returns the index of the "bottom" or -1 if it doesn't exist.
static int findbottom(int[] arr, int s, int e)
{
if (s > e) return -1;
if (s == e) return s;
int m = (s + e) / 2;
if (m == s || m == e) return -1;
int mm1 = arr[m - 1];
int mp1 = arr[m + 1];
if (mm1 >= arr[m] && mp1 >= arr[m]) return m;
if (mm1 > mp1) return findbottom(arr, m, e);
return findbottom(arr, s, m);
}
import java.util.Arrays;
public class LocalMinimumInArray {
public static int getLocalMinimum(int [] arr){
int n = arr.length;
if(n<3 || arr[0] < arr[1] || arr[n-1] < arr[n-2] ) throw new IllegalArgumentException("...");
int p = 1;
int q = n-2;
// check p and q
if(arr[p] <= arr[p+1]) return p;
if(arr[q] <= arr[q-1]) return q;
while(p < q){
int m = (p+q)/2;
if(arr[m-1] < arr[m]){
q = m-1;
if(arr[q] <= arr[q-1]) return q;
continue;
}
if(arr[m] > arr[m+1]){
p = m+1;
if(arr[p] <= arr[p+1]) return p;
continue;
}
return m;
}
return p;
}
public static void main(String[] args) {
int [] arr = { 8,8,5,4,5,5,6,8 };
test(arr);
}
private static void test(int[] arr) {
int idx = getLocalMinimum(arr);
System.out.println("Local minimum in " + Arrays.toString(arr)+ " is at index " + idx+": "+ arr[idx]);
}
}
The triplet can be found out by using binary search in the following way. You can test the below code:
#include <stdio.h>
#include <stdlib.h>
int findTriplet(int arr[],int low,int high)
{
if(low==high)
return 0;
else if(low==high+1)
return 0;
else
{
int mid=low+(high-low)/2;
if(arr[mid-1]>=arr[mid]&&arr[mid]<=arr[mid+1])
return mid;
findTriplet(arr,low,mid-1);
findTriplet(arr,mid+1,high);
}
}
int main()
{
int arr[]={4,3,4};
int n=sizeof(arr)/sizeof(arr[0]);
int i=findTriplet(arr,0,n-1);
if(i==0)
printf("No triplet exists");
else
{
printf("Triplet exists and it is \n");
printf("%d %d %d",arr[i-1],arr[i],arr[i+1]);
}
}
logic is good, but I think it is not using binary search as we are traversing both sides of array and order will be of O(n).
No i think it follows the concept of binary search as you can also review it in wikipedia under the tag recursion for the same.
Have you ran and checked it, because u kept low and high as fixed. you are only incrementing/decrementing mid. Correct me, if i am wrong.
No low and high are not fixed .Remember this is recursion and when you are calling function(arr,low,mid-1) then high=mid-1 and when function(arr,mid+1,high) then low=mid+1. Also mid changes everytime as low and high are also changing..
This is O(N). Note that each recursive call tries searching for the left and then the right. So if the answer is very near the right end of the array, essentially you will be calling the method almost N times before you stumble upon the answer.
For it to be sublinear, you will need to be able to skip checking on some parts of the array.
@Sunny This is binary search everytime i am dividing the array into two parts and whenever the element satisfies the given condition i am returning the index so the comparison of the rest of the elements is avoided. And please first read or explore about binary search recursive version in wikipedia or somewhere else.Since i cannot post the link here i am copying the code for a recursive binary search given in wikipedia. Please read it:
int binary_search(int A[], int key, int imin, int imax)
{
// test if array is empty
if (imax < imin)
// set is empty, so return value showing not found
return KEY_NOT_FOUND;
else
{
// calculate midpoint to cut set in half
int imid = midpoint(imin, imax);
// three-way comparison
if (A[imid] > key)
// key is in lower subset
return binary_search(A, key, imin, imid-1);
else if (A[imid] < key)
// key is in upper subset
return binary_search(A, key, imid+1, imax);
else
// key has been found
return imid;
}
}
- m3th0d July 07, 2013