2015-10-18 10:42:52 +08:00

142 lines
3.2 KiB
C++

// Source : https://oj.leetcode.com/problems/find-peak-element/
// Author : Hao Chen
// Date : 2014-12-05
/**********************************************************************************
*
* A peak element is an element that is greater than its neighbors.
*
* Given an input array where num[i] ≠ num[i+1], find a peak element and return its index.
*
* You may imagine that num[-1] = num[n] = -∞.
*
* For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.
*
* click to show spoilers.
*
* Note:
* Your solution should be in logarithmic complexity.
*
* Credits:Special thanks to @ts for adding this problem and creating all test cases.
*
**********************************************************************************/
#include <iostream>
#include <vector>
using namespace std;
/*
* Binary search is common idea here.
*
* However, you need to think about two senarios:
*
* 1) Becasue we need check `num[mid-1]`, `num[mid]`, `num[mid+1]`,
* So, we need make sure there hasn't out-of-boundary issue.
*
*
*
* 2) There are multiple Peak elements.
*
* For example: [1,2,1,2,1], or [ 1,2,3,1,2,1]
*
* LeetCode doesn't tell you what the expected result is. I guess:
*
* 2.1) for [1,2,1,2,1] you can return either 1 or 3, because both them are peak elements
*
* 2.1) for [1,2,3,2,4,2,1] it should return 4, because num[4] is the real peak. but Leetcode accept either 2 or 4
*
*/
int findPeakElement(const vector<int> &num) {
int n = num.size();
int low = 0;
int high = n - 1;
int mid = 0, v1, v2;
while ( low < high ) {
// Find the index of middle element
mid = low + ( high - low ) / 2;
// Compare middle element with its neighbours (if neighbours exist)
if ( ( mid == 0 || num[mid] > num[mid-1] ) &&
( mid == n-1 || num[mid] > num[mid+1] ) ){
return mid;
}
// If middle element is not peak and its left neighbor is greater than it
// then left half must have a peak element
if (mid >0 && num[mid-1] > num[mid]){
high = mid - 1;
// If middle element is not peak and its right neighbor is greater than it
// then right half must have a peak element
}else{
low = mid + 1;
}
}
return low;
}
void printVector(vector<int> &n) {
cout << "[ ";
int i;
for(i=0; i<n.size(); i++){
cout << n[i] << (i==n.size()-1 ? " ]" : ", ");
}
cout << endl;
}
void test(int a[], int n) {
vector<int> v(a, a+n);
cout << "Peak Index = " << findPeakElement(v) << "\t";
printVector(v);
}
#define TEST(a) test(a, sizeof(a)/sizeof(a[0]))
int main(int argc, char**argv)
{
int n0[] = {1};
TEST(n0);
int n1[] = {1,2};
TEST(n1);
int n2[] = {2,1};
TEST(n2);
int n3[] = {1,2,3};
TEST(n3);
int n4[] = {3,2,1};
TEST(n4);
int n5[] = {1,2,3,2};
TEST(n5);
int n6[] = {0,1,2,9,7,5,4,2,1};
TEST(n6);
int n7[] = {1,2,1,2,1};
TEST(n7);
int n8[] = {1,2,1,2,3,1};
TEST(n8);
int n9[] = {1,2,3,2,4,2,1};
TEST(n9);
int n10[] = {1,3,1,2,1,3,1};
TEST(n10);
return 0;
}