【LeetCode】每日一题

109 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情

162. 寻找峰值

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

给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞ 。

你必须实现时间复杂度为 O(log 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。
「提示:」
1. 1 <= nums.length <= 1000
2. -231 <= nums[i] <= 231 - 1
3. 对于所有有效的 i 都有 nums[i] != nums[i + 1]

解题思路

数组从中间分成两个数组 L 和 R。比较 L 最后一个值 l 与 R 的第一个值 r 的大小。如果 l > r 则数组 L 必有一个及以上原数组的峰值,取数组 L 再做上一步。反之则数组 R 必有一个及以上原数组的峰值,取数组 R 再做上一步。当数组长度为 1 时。其值为峰值。

代码实现

​
​
var findPeakElement = function(nums) {
    let lIndex = 0; // 虚拟数组第一个元素下标
    let rIndex = nums.length - 1; // 虚拟数组最后一个元素下标
    let mid; // 数组中间元素下标。
    while (lIndex < rIndex) { // 当数组长度不为 1 时。
        mid = Math.floor((lIndex + rIndex) / 2); // 取当前虚拟数组的中间元素的下标(当数组长度为偶数时取小的那个),可将虚拟元素隔开成两个数组。
        if (nums[mid] > nums[mid + 1]){ // 比较左边数组最后一个元素与右边数组的第一个元素的大小
            rIndex = mid; // 左边数组最后一个元素大、则取左边数组
        } else {
            lIndex = mid + 1; // 右边数组第一个元素大、则取右边数组
        }
    }
    return lIndex;
};

如果你对这道题目还有疑问的话,可以在评论区进行留言;