二分查找法解决寻找峰值

题目 寻找峰值

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

给你一个整数数组 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 <= nums.length <= 1000
-231 <= nums[i] <= 231 - 1
对于所有有效的 i 都有 nums[i] != nums[i + 1]

解题
1、先确定nums[0]和nums[n-1]是不是峰值,如果是峰值返回即可。
2、如果nums[0]和nums[n-1]不是峰值,那么继续查找峰值。
nums[0]不是峰值,nums[1]>nums[0],数组开始为上升趋势,nums[n-1]不是峰值,nums[n-2]>nums[n-1],数组结束为下降趋势;数组开始上升,结尾下降,中间数字相邻不相等,可确定整个数组中肯定有大于等于1个峰值存在。
3、查找其中的峰值可用二分查找法,取中间值m,判断中间值是否为峰值,如果(m-1)>m,则舍弃(m+1)之后的数组,继续在1~m中查找,如(m+1)>m则舍弃0 ~ (m-1)之前的数组,在(m+1) ~ n-2中查找。

public static int findPeakElement(int[] arr) {
        if(arr.length == 1){
            return 0;
        }
        //判断第一位数是不是峰值
        //如果第一位数大于第二位数那么第一位数即为峰值
        if (arr[0] > arr[1]) {
            return 0;
        }
        //判断最后一位数是不是峰值
        //如果倒数第二位数小于最后一位数 那么 最后一位数即为峰值
        if (arr[arr.length - 1] > arr[arr.length - 2]) {
            return arr.length - 1;
        }
        int l = 1, r = arr.length - 2, m = 0,ans = -1;
        while (l <= r) {
            m = (l + r) / 2;
            if (arr[m] > arr[m - 1] && arr[m] > arr[m + 1]) {
                ans = m;
                break;
            } else if (arr[m] < arr[m - 1]) {
                r = m - 1;
            } else {
                l = m + 1;
            }
        }
        return ans;
    }
  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
假设峰值定义为在数组中找到一个元素,其左右上下四个元素都小于它,则可以采用以下方在二维数组中寻找峰值: 1. 遍历数组的第一行,找到该行的最大值及其所在的列号,记为max_col。 2. 在第max_col列中,找到该列的最大值及其所在的行号,记为max_row。 3. 判断max_row行max_col列的元素是否为峰值,如果不是,则比较该元素与其上下左右四个元素的大小,移动到更大的元素所在的位置,重复步骤3。 4. 如果max_row行max_col列的元素是峰值,则返回该元素。 代码示例(Python): ``` def find_peak(matrix): rows, cols = len(matrix), len(matrix[0]) max_col = 0 for j in range(cols): if matrix[0][j] > matrix[0][max_col]: max_col = j max_row = 0 for i in range(rows): if matrix[i][max_col] > matrix[max_row][max_col]: max_row = i if (max_row == 0 or matrix[max_row - 1][max_col] <= matrix[max_row][max_col]) and \ (max_row == rows - 1 or matrix[max_row + 1][max_col] <= matrix[max_row][max_col]) and \ (max_col == 0 or matrix[max_row][max_col - 1] <= matrix[max_row][max_col]) and \ (max_col == cols - 1 or matrix[max_row][max_col + 1] <= matrix[max_row][max_col]): return matrix[max_row][max_col] elif max_row > 0 and matrix[max_row - 1][max_col] > matrix[max_row][max_col]: return find_peak(matrix[:max_row, :]) elif max_row < rows - 1 and matrix[max_row + 1][max_col] > matrix[max_row][max_col]: return find_peak(matrix[max_row + 1:, :]) elif max_col > 0 and matrix[max_row][max_col - 1] > matrix[max_row][max_col]: return find_peak(matrix[:, :max_col]) else: return find_peak(matrix[:, max_col + 1:]) ``` 该代码采用了递归的方式,在每次比较中缩小数组的范围,直到找到峰值为止。时间复杂度为O(mlogn),其中m和n分别为数组的行数和列数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值