当前位置: 首页 > news >正文

数据结构与算法之数组寻找峰值分而治之


这一篇分享一道在数组中寻找峰值的题目,使用到分而治之,二分查找等思想。本文章会讲解这个二分查找的本质,以及为什么要用二分查找,它能解决哪一类题目?


目录:
一.题目及其要求
1.分而治之
2.题目思路
3.具体做法+配图演示
4.复杂度分析
二.剖析二分查找
1.本质
2.优点
3.适用场景

一.题目及其要求

1.给定一个长度为n的数组,返回其中任何一个峰值的索引
2.峰值元素是指其值严格大于左右相邻值的元素
3.数组两个边界可以看成是最小,nums[−1]=nums[n]=−∞
4.峰值不存在平的情况,即相邻元素不会相等
5.峰值从第二个数开始,不考虑边界的-∞

如输入[2,4,1,2,7,8,4]时,会形成两个山峰,一个是索引为1,峰值为4的山峰,另一个是索引为5,峰值为8的山峰,如下图所示:

示例:

输入:[2,4,1,2,7,8,4]
返回值:1 说明:4和8都是峰值元素,返回4的索引1或者8的索引5都可以
输入:[1,2,3,1]
返回值:2 说明:3 是峰值元素,返回其索引 2

1.分而治之

分治即“分而治之”,意思就是把一个复杂大问题分成若干个简单的小问题,当小问题解决后,大问题也就迎刃而解。“分”指的是将一个大而复杂的问题划分成多个性质相同但是规模更小的子问题,子题继续按照这样划分,直到问题可以被轻易解决;“治”指的是将子问题单独进行处理。经过分治后的子问题,将若干个子问题进行合并才能得到原问题的解,因此整个分治过程经常用递归来实现。

2.题目思路

因为题目只需要找到其中一个波峰,因此不断地往高处走,一定会有波峰。那我们可以每次找一个标杆元素,将数组分成两个区间,每次就较高的一边走,因此也可以用分治来解决,而标杆元素可以选择区间中点。

//右边是往下,不一定有坡峰
if(nums[mid] > nums[mid + 1])right = mid;
//右边是往上,一定能找到波峰
elseleft = mid + 1;

下面配图进行理解上面代码:

3.具体做法+配图演示

  • 1:二分查找首先从数组首尾开始,每次取中间值,直到首尾相遇。

  • 2:如果中间值的元素大于它右边的元素,说明往右是向下,我们不一定会遇到波峰,但是那就往左收缩区间。

  • 3:如果中间值大于右边的元素,说明此时往右是向上,向上一定能有波峰,那我们往右收缩区间。

  • 4:最后区间收尾相遇的点一定就是波峰。

下面是配图演示:

4.代码实现

class Solution {
public:int findPeakElement(vector<int>& nums) {int left = 0;int right = nums.size() - 1;//二分法while(left < right){ int mid = (left + right) / 2;//右边是往下,不一定有坡峰if(nums[mid] > nums[mid + 1])right = mid;//右边是往上,一定能找到波峰elseleft = mid + 1;}//其中一个波峰return right; }
};

4.复杂度分析

  • 时间复杂度:O(log2n),二分法最坏情况对整个数组连续二分,最多能分log2n次。

  • 空间复杂度:O(1),常数级变量,无额外辅助空间。

二.剖析二分查找

1.本质

二分查找的本质是二段性,二分查找的过程本质是对可行区间的压缩。只要满足二段性的问题都可以用二分查找解决。

2.优点

通过对有序数组进行逐步缩小范围的操作,将查找时间从线性时间降低到了对数时间,因此它是一种非常高效的搜索算法。

3.适用场景

二分查找的时间复杂度为O(log n),比其他搜索算法的复杂度要低得多,因此它被广泛应用于各种搜索场景中。

在这里二段性的体现是峰值的左边单调增,右边单调减。你可能会反驳给我们的数值不只有一个峰值,但是只要我们控制好条件,一定可以把范围压缩到只有一个峰值的情况,来看看该怎么处理:

  • nums[mid] < nums[mid + 1]说明在“上坡”,则可以使left = mid + 1(因为mid肯定不是峰值),向“峰”处压缩

  • nums[mid] > nums[mid + 1]说明在“下坡”,则应该使right = mid(mid可能是峰值),往“峰”处压缩

虽然开始left和right之间可能有多个峰值,但是随着left和right不断逼近,最后两者之间一定会压缩到一个峰值上,因为两者都是向“峰”不断靠近的,但是不会超过最终的“峰”。

望上文对你有帮助,谢谢你的阅览,后面会持续分享算法题目,大家可以关注一下。

2023.02.18

From:努力进大厂的新青年

http://www.lryc.cn/news/12524.html

相关文章:

  • Metasploit 使用篇
  • Java岗面试题--Java并发(日积月累,每日三题)
  • Prometheus监控案例之blackbox-exporter
  • Makefile基础使用和实战详解
  • Go基础-变量
  • 【算法】三道算法题目单词拆分,填充每个节点的下一个右侧节点指针以及组合总和
  • 【算法】刷题路线(系统+全面)
  • Fiddler的报文分析
  • Spring 中,有两个 id 相同的 bean,会报错吗
  • Mysql数据库的时间(4)一查询数据库时间注意点
  • 一起学 pixijs(2):修改图形属性
  • LeetCode 121. 买卖股票的最佳时机
  • shell脚本内调用另外一个shell脚本的几种方法
  • Linux C++ 多进程下write写日志问题思考
  • MySQL的四种事务隔离级别
  • 方法区和元空间有什么关系?
  • 2023VNCTF的两道(暂时)
  • JDK版本区别
  • Android 基础知识4-2.8 TableLayout(表格布局)详解
  • SQL代码编码原则和规范
  • 【博客627】gobgp服务无损变更:graceful restart特性
  • 一起学 pixijs(1):常见图形的绘制
  • 2023年PMP考试教材有哪些?(含pmp资料)
  • centos7防火墙工具firewall-cmd使用
  • js html过滤所有标签格式并清除所有nbsp;
  • 「技术选型」深度学习软件如何选择?
  • 加油站会员管理小程序实战开发教程13
  • Go语言Web入门之浅谈Gin框架
  • 《MySQL学习》 MySQL优化器选择如何选择索引
  • uniapp 悬浮窗(应用内、无需授权) Ba-FloatWindow2