i trying find minimum element in sorted array has been rotated.
example:
1 2 3 4 5 => sorted 3 4 5 1 2 => rotated => find min in in o(log n) i have tried write code :
#include <iostream> #include <vector> #include <algorithm> using namespace std; int bs(vector<int> a) { int l =0, r = a.size()-1; while(l<=r) { int mid = l + (r-l)/2; // mid guaranteed in range if(a[mid-1]>a[mid]) return a[mid]; if(a[mid]>a[l]) { l=mid+1 ; continue; } else { r = mid-1 ; //mid has been checked } } } int main() { vector<int> = {1,2,3,5,6,7,8,9,10}; rotate(a.begin(),a.begin()+4,a.end()); // make 6 head for(auto x:a) cout<<x<<endl; cout <<"min " <<bs(a) <<endl; return 0; } i output:
6 7 8 9 10 1 2 3 5 min 3 , wrong. guess manipulating binary search conditions adapt problem, can't figure out wrong.
my method similar this, , think doing logically correct, of course wrong thinking.
you have right strategy, have not thought invariants.
i assume elements distinct. without this, can't done in o(log n) time. (consider case elements 0 except single 1.)
if a[0] < a[size-1], there no effective rotation, a[0] min.
otherwise there 2 increasing runs a[0]<a[1]<...<a[k-1] , a[k]<a[k+1]<...<a[size-1], know a[k-1]>a[k].
we want find k.
start - did - bracket [0, size-1] of guesses.
the invariant bracket must contain k. true initial bracket!
to ensure termination, must make smaller during each iteration. when interval has 1 element, i.e. lo == hi, have answer.
computing new guess showed,
int mid = (lo + hi) / 2; now, possibilities? mid lies either in [0, k-1] or [k, size-1].
if former, know mid <= k-1. can make bracket [mid+1, hi] while maintaining invariant. note makes bracket smaller, ensuring termination.
if it's latter, know mid >= k, can use [lo, mid]. note can't [lo, mid-1] because mid might equal k, breaking invariant.
this raises concern. if calculation of mid produce mid == hi, new bracket same old. we'd have no progress , infinite loop. happily never happens because (lo + hi) / 2 < hi whenever lo < hi.
the last piece of puzzle how tell run mid lies in. easy. if a[mid] >= a[0], know lies in first run. else lies in second.
wrapping in code:
if (a[0] < a[size - 1]) return 0; int lo = 0, hi = size - 1; while (lo < hi) { int mid = (lo + hi) / 2; if (a[mid] >= a[0]) lo = mid + 1; else hi = mid; } return lo;
Comments
Post a Comment