一.題目連接:算法
https://leetcode.com/problems/find-peak-element/數組
二.題目大意:spa
給定一個長度爲N的一維數組,數組是無序的,要求找到數組中的極大值(或局部最大值),並返回該極大值的下標,並假設 nums[-1] = nums[n] = -∞
.;當某元素同時大於它兩邊的元素時,則該元素是數組中的一個極大值,數組中若存在多個極大值,則返回任意一個便可。.net
算法的時間複雜度要求爲log級別。code
三.題解:blog
這個問題的最直觀的解法,就是遍歷一遍數組,而後判斷每一個元素是否符合極大值的條件,可是時間複雜度爲O(N),不符合題目的要求。既然要求是對數級別的時間複雜度,那就不妨利用二分法的思想來查找符合條件的元素。element
代碼以下:leetcode
class Solution { public: int findPeakElement(vector<int>& nums) { if(nums.empty()) return -1; int len = nums.size(); int low = 0; int high = len - 1; while(low < high - 1)//至少要省出一箇中間值來,因此low < high -1 { int mid = ((high - low) >> 1) + low;//一位運算符的優先級比較低,因此必定加上括號 if(nums[mid] > nums[mid + 1] && nums[mid] > nums[mid - 1]) return mid; else if(nums[mid] < nums[mid + 1]) { if (low == mid)//特殊狀況,必須經過low = mid + 1跳出這種循環 low = mid + 1; else low = mid; } else high = mid; } return nums[low] > nums[high] ? low : high;//有可能還沒找到mid就跳出循環了,此時low和high必有一個知足條件 } };
該算法的時間複雜度爲O(logN),空間複雜度爲O(1),可以知足題目的要求。有幾點須要注意:get
1.循環的終止條件爲low < high -1,由於極大值要同時大於兩邊的元素,因此至少要有三個值,不然就跳出循環。io
2.有種特殊狀況,就是low = mid後,再次更新mid的話,low與mid的值仍是相同,至關於陷入了死循環,此時經過low = mid + 1跳出死循環。
3.若是在循環中沒有返回mid的話,可能數組只有一個元素,也可能只有數組的末尾元素纔是極大值,因此最後要判斷一下low和high的值,並返回其中較大的。
四.題目擴展:
若是數組爲二維數組的話,如何找到局部最大值(極大值)?
通常有三種方法:直接遍歷、利用二分法、利用畫圈法(分治)。具體能夠參考:https://www.jianshu.com/p/b4f5cb071f04 或者 https://blog.csdn.net/m0_37747541/article/details/79629457