1. 程式人生 > >Leetcode ---- 162. 尋找峰值

Leetcode ---- 162. 尋找峰值

題目:

峰值元素是指其值大於左右相鄰值的元素。

給定一個輸入陣列 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素並返回其索引。

陣列可能包含多個峰值,在這種情況下,返回任何一個峰值所在位置即可。

你可以假設 nums[-1] = nums[n] = -∞

示例 1:

輸入: nums = [1,2,3,1]
輸出: 2
解釋: 3 是峰值元素,你的函式應該返回其索引 2。

示例 2:

輸入: nums = [1,2,1,3,5,6,4]
輸出: 1 或 5 
解釋: 你的函式可以返回索引 1,其峰值元素為 2;
     或者返回索引 5, 其峰值元素為 6。

說明:

你的解法應該是 O(logN) 時間複雜度的。

 

思路:

1. 最粗暴的方法,即下文註釋的方法,O(N)的時間複雜度,從頭迴圈到尾,逐個判斷

2. 仔細審題我們發現,區間的左右兩邊是較區間外的元素大。因此,我們可以想象,為了不讓兩端元素成為峰值,兩端元素從外到內逐漸變小,又因為元素值不可能相同,則我們可以想到區間內必然有一個峰值(兩邊元素都比他小)。

在此,我們得到了一個結論,在兩個元素(左元素比它的左邊大,右元素比它的右邊大)之間,必然有一個峰值。程式如下,如此迴圈。一旦發現 begin >= end ,則找到峰值。

 

程式:

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
/*        int flag = 1,i = 1;
        if (nums.size() == 1 || nums[0] > nums[1]){
            return 0;
        }
        else if (nums.empty())
            return -1;
        else if (*(nums.end()-1) > *(nums.end()-2))
            return nums.size()-1;
        while (flag && i < nums.size()){
            if (nums[i] > nums[i-1] && nums[i] > nums[i+1])
                flag = 0;
            else{
                i++;
            }
        }
        return i;*/

        int begin = 0,end = nums.size() - 1;
        int mid1, mid2;
        while (begin < end){
            mid1 = (begin + end)/2;
            mid2 = mid1 + 1;
            
            if (nums[mid1] > nums[mid2]){
                end = mid1;
            }
            else{
                begin = mid2;
            }
        }
        return begin;
    }
};