Leetcode 162:寻找峰值(最详细的解法!!!)

版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/83780912

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

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

解题思路

由于算法的时间复杂度限制,所以我们不能使用直接遍历的方法。由于时间复杂度的特殊性,所以我们首先想到的解法就是通过二分搜索法,但是这不是一个有序数组,怎么办?我们一直有一个条件没有注意nums[-1]=nums[n]=-inf。我们可以将两端设置为端点,然后考虑中间元素。

  1 2 1 3 5 6 4
i       k       j

此时我们应该考虑nums[k]nums[k+1]的关系。如果我们nums[k]>nums[k+1],我们应该让j=k,因为k很可能就是峰值(因为右边小,而左边存在-inf)。而如果nums[k]<nums[k+1],我们应该让i=k+1,因为k+1可能是峰值(同理)。对于nums[k]==nums[k+1]的情况,我们放到第二种情况了考虑就可以了。最后我们要考虑边界问题,因为我们最后得到的是峰值位置,所以我们的ij应该从0len(nums)-1开始(我们此时要把0len(nums)-1也要考虑进去,因为这两个位置也可能是峰值位置)。

class Solution:
    def findPeakElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        l, r = 0, len(nums)-1
        while l < r:
            mid = (l + r)//2
            if nums[mid] <= nums[mid+1]:
                l = mid + 1
            else:
                r = mid

        return l

最后的代码非常简洁。

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

猜你喜欢

转载自blog.csdn.net/qq_17550379/article/details/83780912
今日推荐