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

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

说明

此文是课程https://edu.csdn.net/course/detail/38771 的讲义。

源码下载:https://download.csdn.net/download/he_zhidan/88458478

本文涉及的基础知识点

二分查找算法合集

题目

长度为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]。

2023年11月14整补

有读者反应看不懂,感谢他的建议,特增补如下。

定义

原始数组的连续区域称为子数组。如果一个子数组的首元素在原始数组的索引为i,尾元素在原始数组的索引为j,则用nums[i,j]表示此子数组,也可以用nums[i,j+1)表示。如果nums[i,j]同时符合以下两个条件,则是好子数组。

一,i为0或nums[i]>nums[i-1]。

二,j为n-1或nums[j]>nums[j+1]

推论

一,如果好子数组nums[i,j]的长度为1,则i就是峰值。

二,如果好子数组nums[i,j]的长度大于1,则从nums[i,j]找出一个比nums[i,j]短的好子数组nums[i1,j1]。

三,由于长度不断变短,长度一定会变为1。

举例

1 2

1 2 =>2 (1不是好子数组 2是,长度降为1结束)

2 1

2  1 =>2 (2是好子数组 ,1不是,长度降为1结束)

1 2 3

1 2 3 => 2 3(1不是好子数组,2 3是)=> 3(3是好数组长度降为1结束)

3 2 1

1 2 3 => 3

1 3 2

1 3 2 => 3 2 => 3

1到4

1 2 3 4 => 3 4 => 4

1 2 4 3 => 4 3 => 4

1 3 2 4=> 1 3 => 3

1 3 4 2 => 4 2 => 4

1 4 2 3=> 1 4=> 4

1 4 3 2=> 1 4=> 4

...

2 4 1 3 => 2 4 => 4

其它

1 2 3 4 5 6 7 8 => 5 6 7 8 => 7 8 => 8

9 8 7 6 5 4 3 2 1 => 9 8 7 6 => 9 8 = > 9

1 3 5 7 9 8 6 4 2 => 9 8 6 4 2 = > 9 8 => 9

总结

将好子数组nums[i,j] 分成左右两个子数组nums[i,mid)和nums[mid,j]

如果nums[mid]> nums[mid-1] 则nums[mid,j]是好子数组

否则 nums[i,mid)是好子数组

分析

假定

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);
}

其它

学院课程

基础算法的C++实现课程,请点击下面的CSDN学院的链接。

2024年1月15之前完全免费,之后绝大部分免费

https://edu.csdn.net/course/detail/38771

C#入职培训

此课程的目的:让新同事更快完成从学生到C#程序员的转换,更快上手完成C#的开发工作。

https://edu.csdn.net/course/detail/38768

C++入职培训

让新同事更快完成从学生到C++程序员的转换,更快上手完成C++的开发工作。

https://edu.csdn.net/course/detail/32049

运行验证环境

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

每天都补充正能量

好好学习,天天向上。

事无终始,无务多业。

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

相关下载

如果你时间宝贵,只想看精华,请到CSDN下载频道下载《闻缺陷则喜算法册》doc版

https://download.csdn.net/download/he_zhidan/88348653


相关文章
|
7天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
45 8
|
7天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
33 7
|
1月前
|
存储 算法 C++
高精度算法(加、减、乘、除,使用c++实现)
高精度算法(加、减、乘、除,使用c++实现)
384 0
高精度算法(加、减、乘、除,使用c++实现)
|
1月前
|
分布式计算 监控 Hadoop
Hadoop-29 ZooKeeper集群 Watcher机制 工作原理 与 ZK基本命令 测试集群效果 3台公网云服务器
Hadoop-29 ZooKeeper集群 Watcher机制 工作原理 与 ZK基本命令 测试集群效果 3台公网云服务器
37 1
|
1月前
|
存储 算法 决策智能
【算法】博弈论(C/C++)
【算法】博弈论(C/C++)
|
1月前
|
存储 算法 C++
【算法】哈希映射(C/C++)
【算法】哈希映射(C/C++)
|
1月前
|
机器学习/深度学习 人工智能 算法
【算法】最长公共子序列(C/C++)
【算法】最长公共子序列(C/C++)
|
1月前
|
人工智能 算法 BI
一篇带你速通差分算法(C/C++)
一篇带你速通差分算法(C/C++)
|
22天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
7天前
|
算法 数据挖掘 数据安全/隐私保护
基于FCM模糊聚类算法的图像分割matlab仿真
本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。