寻找峰值(二分查找思想)

本文介绍了两种方法寻找给定数组中的峰值元素:暴力遍历法,通过检查相邻元素比较找出峰值;以及二分查找法,利用递增或递减趋势缩小搜索范围。特别考虑了边界条件,如数组只有一个元素或边界值的情况。
摘要由CSDN通过智能技术生成

解法一:暴力求解

int findPeakElement(int* nums, int numsLen ) {
    // write code here
    for (int i = 1; i < numsLen - 1; i++) {
        if ((nums[i] > nums[i - 1]) && (nums[i] > nums[i+1])) {
            return i;
        }
    }
    if (nums[numsLen - 1] > nums[numsLen - 2]) {
        return numsLen - 1;
    }
    return 0;
}

题中明确说明:nums[-1] = nums[n] = −∞,所以要特别注意 nums[0] 和 nums[numsLen - 1]

直接遍历数组从 1 到 numsLen-2,要注意边界的问题,当nums[0] > nums[1]时,返回0
当 nums[numsLen - 1](最后一个元素) > nums[numsLen - 2](倒数第二个元素)时,返回numsLen - 1 。

解法二:二分思想

中间比右边大,认为从右往左半边递增,则把 right 不断向左靠拢 right=mid ,注意不能是 mid-1 ,因为这个位置有可能就是峰值点。 直到遇到中间比右边小了,意味着数据开始递降了,则 left 向右偏移, left=mid+1 ; 而一旦 mid+1 位置大于了 right ,意味着刚好这个 mid+1 位置,是一个左半边-右往左递降,右半边-右往左递增的点,就是一个峰值点。

示例:
int arr[] = {3, 5, 4, 4, 3, 2, 1} , 这个数组中两边边界都是非峰值点 int left = 0, right = 6;
left=0,right=6,mid=3: arr[3]=4 > arr[4]=3, 则right = mid = 3; //从右往左是递增的

left=0,right=3,mid=1: arr[1]=5 > arr[2]=4, 则right = mid = 1; //从右往左是递增的

left=0,right=1,mid=0: arr[0]=3 < arr[1]=5, 则left = mid + 1 = 1; //从右往左开始递降了 left > right 退出循环, 返回left,也就是1号下标位置。

int findPeakElement(int* nums, int numsLen ) {
    //边界情况处理,1个元素前后都是负无穷 以及 0号位置大于1号位置,-1位置负无穷的情况
    if (numsLen == 1 || nums[0] > nums[1])
        return 0; 
    //末尾位置数据大于上一个位置数据,而nums[numsLen]负无穷的情况
    if (nums[numsLen - 1] > nums[numsLen - 2])
        return numsLen - 1;
    int left = 0, right = numsLen - 1, mid = 0;
    while (left < right) {
        mid = left + (right - left) / 2;
        //中间比右边小,意味着右边肯定有个峰值
        if (nums[mid] < nums[mid + 1]) {
            left = mid + 1;
        }
        //否则在左边包括当前位置肯定有个峰值
        else {
            right = mid;
        }
    }
    return left;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值