一.题目连接:算法
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