LeetCode_Array_162. Find Peak Element寻找峰值(C++/Java)

目录

1,题目描述

英文描述

中文描述

2,解题思路

2.1 基本原理

2.2 算法

3,AC代码

C++

Java

4,解题过程

第一博


1,题目描述

英文描述

A peak element is an element that is greater than its neighbors.

Given an input array nums, where nums[i] ≠ nums[i+1], find a peak element and return its index.

The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.

You may imagine that nums[-1] = nums[n] = -∞.

Example 1:

Input: nums = [1,2,3,1]
Output: 2
Explanation: 3 is a peak element and your function should return the index number 2.
Example 2:

Input: nums = [1,2,1,3,5,6,4]
Output: 1 or 5 
Explanation: Your function can return either index number 1 where the peak element is 2, 
             or index number 5 where the peak element is 6.
Follow up: Your solution should be in logarithmic complexity.

中文描述

峰值元素是指其值大于左右相邻值的元素。

给定一个输入数组 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) 时间复杂度的。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-peak-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2,解题思路

2.1 基本原理

首先注意几点:

  • 1,极值点: 一阶导数为0的点, (其值大于左右两边相邻数的值);
  • 2,nums[i] ≠ nums[i+1]:即任一个数,与其左右两边相邻的值都不相同;
  • 3,nums[-1] = nums[n] = -∞:保证了算法的数学理论支持;

其中第2、3点,保证了该数学思路的有效性:

设位于中间位置的元素坐标为mid,由于nums[mid]  nums[mid + 1],所以只有两种情况:

1)nums[mid] > nums[mid + 1]:区间内[-1, mid+1]内含有极值点

由于nums[-1] = -∞ < nums[mid],所以图形如下:可以得出一个结论,nums[-1] 与 nums[mid + 1]之间,必定存在一个极值(直观理解一下,对于mid来说,左边至少一个值nums[-1]小于nums[mid],右边nums[mid + 1]也小于nums[mid],所以区间内[-1, mid+1]最起码会有一个凸起的点,使得左右两边的值小于这个点)

2)nums[mid] < nums[mid + 1]:区间内[mid, n]内含有极值点

同理

2.2 算法

1,声明左右指针left,right标明左右边界;

2,只要left < right,进入循环;(left == right时,确定极值点)

3,判断nums[mid] 与nums[mid + 1]的大小关系(nums[i] ≠ nums[i+1],所以只有>、<两种情况);

  • nums[mid] < nums[mid+1]:极值点在区间[mid,right]中,更新左边界left = mid + 1;
  • nums[mid] > nums[mid+1]:极值点在区间[left,mid + 1]中,更新右边界right = mid;

(通过循环步骤3,可以确保区间内必定含有极值点,且区间长度不断缩小,所以只需要将区间大小缩小至1,即可得到极值点)

4,跳出循环,表示左右边界重合,即区间大小变为1,可以确定极值点 = left = right;

3,AC代码

C++

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        int left = 0, right = nums.size() - 1, mid = 0;
        while(left < right) {
            mid = (left + right) / 2;
            if(nums[mid] < nums[mid + 1]) 
                left = mid + 1;
            else 
                right = mid;
        }
        return left;    // 此时左右指针重合 返回左指针坐标即可
    }
};

Java

class Solution {
    public int findPeakElement(int[] nums) {
        int left = 0, right = nums.length - 1, mid = 0;
        while(left < right) {
            mid = (left + right) / 2;
            if(nums[mid] < nums[mid + 1])
                left = mid + 1;
            else
                right = mid;
        } 
        return left;
    }
}

4,解题过程

第一博

题目要求是O(logN), 显然是用二分法, 但是没有思路. 最后在评论区中找到了答案: 原来是利用高等数学中关于极值的性质, 

©️2020 CSDN 皮肤主题: 岁月 设计师:pinMode 返回首页