Leetcode 162 Find Peak Element 查找峰值元素(极大值)

来源:互联网 发布:卓智网络是国企 编辑:程序博客网 时间:2024/06/06 08:39

原题地址

https://leetcode.com/problems/find-peak-element/

题目描述

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.
给出一个不含重复元素的数组num,找出其中的峰值元素并返回其索引(下标)值.

The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.
这个数组可能含有多个峰值元素,在这种情况下返回任意一个峰值元素的下标都可以.

You may imagine that num[-1] = num[n] = -∞.
假设nums[-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.
例如,在数组 [1, 2, 3, 1] 中,3是峰值元素,你的函数需要返回下标2.

spoilers.
挑战.
Note:
注意:

Your solution should be in logarithmic complexity.
你的方法的时间复杂度需要为对数级别复杂度

解题思路一 O(n) 比较次数2n

非常暴力的解决方法,我们遍历所有元素,判断其是否大于前后的元素即可.

代码一

int findPeakElement(int* nums, int numsSize) {    if (numsSize == 1) return 0;    if (*nums > *(nums + 1)) return 0;    int i = 1;    for (; i < numsSize - 1; ++i) {        if (*(nums + i) > *(nums + i - 1) && *(nums + i) > *(nums + i + 1))            return i;    }    return numsSize - 1;}

完整代码https://github.com/Orange1991/leetcode/blob/master/162/c/main.c

解题思路二 O(n) 比较次数n

对于上述解法,我们发现有一个可以改进的地方:

  • 对于第0个元素,nums[0] > nums[-1]是一定成立的,因此如果nums[0] > nums[1]则返回0
  • 如果nums[0] < nums[1],那么对于第1个元素,判断式中的nums[i] > nums[i-1]是显然成立的.实际上这个判断在上一次循环中已经判断过了,程序执行到i=1就已经说明nums[1] > nums[0]了,同理,如果执行到i=2,必有nums[2] > nums[1].因此,在i之前的所有元素是递增的,我们在每次判断时只需要其是否大于后面的元素即可.这样比较次数可以减少到n次.

算法

  1. 我们从0开始往后遍历元素,如果某个元素大于其后面的元素,则该元素就是峰值元素.
  2. 对于最差情况,数组是一个递增的数组,我们遍历到数组末尾,此时由于nums[n]=-∞,所以nums[n-1]>nums[n]且nums[n-1]>nums[n-2],因此最后一个元素就是峰值元素.

代码二

int findPeakElement(int* nums, int numsSize) {    int i = 0;    for (; i < numsSize - 1; ++i)        if (*(nums + i) > *(nums + i + 1))            return i;    return numsSize - 1;}

完整代码https://github.com/Orange1991/leetcode/blob/master/162/c/solution2.c

解题思路三 O(logn)

在解法二中,我们可以发现两个规律,一个是一定存在峰值元素,另一个是在遍历查找过程中对于某个元素之前的所有元素是递增的.其实这两个描述并不准确.我尝试用如下语句来描述这个规律:

  • 规律一:如果nums[i] > nums[i+1],则在i之前一定存在峰值元素
  • 规律二:如果nums[i] < nums[i+1],则在i+1之后一定存在峰值元素

我们可以采用二分查找的方式设计如下算法:

算法

  1. front设为首元素,back设为尾元素
  2. 如果front==end,返回front
  3. 取中间元素center,判定其是否比后面的元素大,是则4,否则5
  4. back=center,跳到1
  5. front=center+1,跳到1

代码三

int findPeakElement(int* nums, int numsSize) {    int front = 0, back = numsSize - 1, center;    while (front <= back) {        if (front == back) return front;        center = (front + back) / 2;        if (*(nums + center) < *(nums + center + 1))            front = center + 1;        else            back = center;    }}

完整代码https://github.com/Orange1991/leetcode/blob/master/162/c/solution3.c


2015/8/3

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 3岁宝宝上火怎么办 上火又受凉感冒怎么办 上火引起的感冒怎么办 奶瓶排气孔漏水怎么办 奶嘴排气孔漏水怎么办 bbox吸管杯漏水怎么办 四个月宝宝拉肚子怎么办 租的房子坐月子怎么办 榨果汁不甜怎么办 宝宝不会喝奶粉怎么办 两个月宝宝不长肉怎么办 打疫苗后发烧怎么办 孕期不爱吃水果怎么办 孕期很少吃水果怎么办 三个月小孩不吃奶粉怎么办 三个月宝宝偏瘦怎么办 破壁机打果汁有沫怎么办 宝宝7个月坐不稳怎么办 婴儿头睡偏了怎么办天 宝宝不爱趴着怎么办 宝宝喜欢竖着抱怎么办 婴儿抱习惯了怎么办 新生儿总让抱着放下就哭可怎么办 三个月宝宝认人怎么办 三个月的宝宝认生怎么办 一岁半宝宝尿黄怎么办 一岁多宝宝尿少怎么办 1岁宝宝一晚没尿怎么办 抗利尿激素少怎么办 小孩夜里尿多怎么办 一岁宝宝认生怎么办 婴儿一个月认生怎么办 婴儿大便带血丝怎么办 两个月宝宝认生怎么办 晚上宝宝认人怎么办 小孩长白头发怎么办 三个月婴儿脚力不足怎么办 未满月宝宝便秘怎么办 婴儿5天没拉大便怎么办 儿童三天没大便怎么办 婴儿4天没拉大便了怎么办