【LeetCode每日一题】——162.寻找峰值

一【题目类别】

  • 二分查找

二【题目难度】

  • 中等

三【题目编号】

  • 162.寻找峰值

四【题目描述】

  • 峰值元素是指其值大于左右相邻值的元素。
  • 给你一个输入数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
  • 你可以假设 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。

六【题目说明】

  • 1 < = n u m s . l e n g t h < = 1000 1 <= nums.length <= 1000 1<=nums.length<=1000
  • − 2 31 < = n u m s [ i ] < = 2 31 − 1 -2^{31} <= nums[i] <= 2^{31} - 1 231<=nums[i]<=2311
  • 对 于 所 有 有 效 的 i 都 有 n u m s [ i ] ! = n u m s [ i + 1 ] 对于所有有效的 i 都有 nums[i] != nums[i + 1] inums[i]!=nums[i+1]

七【题目进阶】

  • 你可以实现时间复杂度为 O ( l o g N ) O(logN) O(logN)的解决方案吗?

八【解题思路】

  • 使用二分查找,首先要明确一点,正常的二分需要数组有序,这里是无序的所以我们可以仍沿用二分的思想,当中间值<右边的元素向右找,当中间值<左边的元素,向左找就可以归纳为那边大向哪边找,为什么呢?因为对于这个无序数组,nums[i] < nums[i+1],那么nums[i+2]有两种情况,一种是nums[i+2]<nums[i+1],那么nums[i+1]就是峰值,另一种是nums[i+2]>nums[i+1],那么根据题意需要向大的这边找,迭代下去就是结果

九【时间频度】

  • 时间复杂度: O ( l o g N ) O(logN) O(logN)

十【代码实现】

  1. Java语言版
package BinarySearch;

public class p162_FindPeakElement {

    public static void main(String[] args) {
        int[] nums = {3, 4, 3, 2, 1};
        int res = findPeakElement(nums);
        System.out.println("res = " + res);
    }

    public static int findPeakElement(int[] nums) {
        // 有两种情况需要特判,第一种情况,数组长度为1,直接返回0
        if (nums.length == 1) {
            return 0;
        }
        // 第二种情况,数组长度为2,比较两个元素,返回大的那个
        if (nums.length == 2) {
            return nums[0] > nums[1] ? nums[0] : nums[1];
        }
        // 接下来就是正常的二分算法
        // 首先定义左右指针
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            // 这里还有两种情况需要特判,和上面的不同,这个判断的是while循环过程中的左右指针
            // 第一种情况,左右指针指向了同一个元素,直接返回
            if (left == right) {
                return right;
            }
            // 第二种情况,左右指针只指向了两个元素,那么返回两个元素中大的下标
            if (right - left == 1) {
                return nums[left] > nums[right] ? left : right;
            }
            int mid = (left + right) / 2;
            // 特判之后就是正常的二分查找
            if (nums[mid] > nums[mid + 1] && nums[mid] > nums[mid - 1]) { // 如果这个元素大于左右两个元素,那么就是我们要找的
                return mid;
            }
            if (nums[mid] < nums[mid + 1]) { // 如果当前元素小于它右边的元素,那么说明要向右边找
                left = mid + 1;
            } else if (nums[mid] < nums[mid - 1]) { // 如果当前元素小于它左边的元素,那么说明要向左边找
                right = mid - 1;
            }
        }
        return -1;
    }

}
  1. C语言版
#include<stdio.h>
#include<stdlib.h>
#include<io.h>

int findPeakElement(int* nums, int numsSize)
{
	if (numsSize == 1)
	{
		return 0;
	}
	if (numsSize == 2)
	{
		return nums[0] > nums[1] ? 0 : 1;
	}
	int left = 0;
	int right = numsSize - 1;
	while (left <= right)
	{
		if (left == right)
		{
			return right;
		}
		if (right - left == 1)
		{
			return nums[left] > nums[right] ? left : right;
		}
		int mid = (left + right) / 2;
		if (nums[mid] > nums[mid + 1] && nums[mid] > nums[mid - 1])
		{
			return mid;
		}
		if (nums[mid] < nums[mid + 1])
		{
			left = mid + 1;
		}
		else if (nums[mid] < nums[mid - 1])
		{
			right = mid - 1;
		}
	}
	return -1;
}

/*主函数省略*/

十一【提交结果】

  1. Java语言版
    在这里插入图片描述

  2. C语言版
    在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IronmanJay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值