C++二分算法的应用:寻找峰值原理、源码及测试用例
  Gjs2egXd7m0h 2023年11月02日 48 0


 说明

此文是课程 的讲义。

源码下载:

题目

长度为n的数组nums,请返回任意一峰值的索引。符合以下条件之一i便是峰值的索引。

n等于1

i等于0


n>1

i等于0

nums[i] >nums[i+1]

n>1

i等于n-1

nums[i] > nums[i-1]

0<i<n-1

nums[i]>nums[i-1]

nums[i]>nums[i+1]


题目保证nums[i]不等于nums[i+1]。

分析

假定

nums[left,r)符合nums[left]>nums[left-1],且nums[r-1]>nums[r]。显然初始情况nums[0,n)符合。

推论一:如果[left,r)的长度为1,则left就是返回的索引。

推论二:假定left < mid<r。如果mid[mid] > mid[mid-1],则nums[mid,r)也符合假定。如果mid[mid] < mid[mid-1],则nums[left,mid)也符合假定。

推论三:推论二也可以也可以理解成分别抛弃[left,mid)和[mid,r)。令mid = left+(r-left)/2,由于r-left>=2,所以left<mid<r。也就是抛弃的子数组不会为空。也就是数组不断变短。等长度为1结束。

时间复杂度

由于每次抛弃一半,所以需要抛弃logn次。故时间复杂度O(logn)

核心代码

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        int left = 0, r = nums.size();
        while (r - left > 1)
        {
            const int mid = left + (r - left) / 2;
            if (nums[mid] > nums[mid - 1])
            {
                left = mid;
            }
            else
            {
                r = mid;
            }
        }
        return left;
    }
};

测试用例

int main()
{
    Solution slu;
    vector<int> nums = { 1,2,3,4 };
    int res = slu.findPeakElement(nums);
    assert(3 == res);
    nums = { 4,3,2,1 };
    res = slu.findPeakElement(nums);
    assert(0 == res);
    nums = { 2,5,3,1 };
     res = slu.findPeakElement(nums);
    assert(1 == res);
}

运行验证环境

Win10 VS2022 Ck++17 或win7 VS2019 C++17

每天都补充正能量

好好学习,天天向上。

事无终始,无务多业。

是故置本不安者,无务丰末。


C++二分算法的应用:寻找峰值原理、源码及测试用例_二分

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
Gjs2egXd7m0h