[M二分] lc153. 寻找旋转排序数组中的最小值(二分+边界情况+好题)

本文主要是介绍[M二分] lc153. 寻找旋转排序数组中的最小值(二分+边界情况+好题),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 1. 题目来源
    • 2. 题目解析

1. 题目来源

链接:153. 寻找旋转排序数组中的最小值

2. 题目解析

一道不错的二分题目。有两种写法,但两种写法的边界情况各不相同,需要考虑清楚。

思路:

  • 数组中可能是完全升序的,也可能是前半段完全大于后半段的旋转的。
  • 升序的很简单,只需要考虑 nums[0] < nums.back() 即可。
  • 关注这个旋转的,可知,nums[0] 就是完全大于后半段的,同理 nums.back() 也是完全小于后半段的。
  • 可以在 [l, r] 区间中取 mid,如果 nums[mid] > nums.back() 说明 mid 落在前半段,且 mid 不包含答案,则可以让 l = mid+1,否则,r = mid 即可。

上述方式使用 nums[mid]>nums.back() 进行判断的。如果写成 nums[mid] < nums[0] 实际上也能判断,此时应当让 r=mid,因为此时的 mid 落在右半段,且让 l=mid+1 即可。
但这样忽略了一个情况,即数组为升序的样例3 这个情况。所以可以通过特判去解决,主体代码仅考虑数组为旋转数组的情况。

这也提示我们一个技巧,可以通过一定的边界、情况的特判,将这些易出错的点特殊处理,再去考虑主体代码的实现。避免想太久。

针对一些整数二分的边界,需要将等号也要考虑清楚。


  • 时间复杂度 O ( log ⁡ n ) O(\log n) O(logn)
  • 空间复杂度 O ( 1 ) O(1) O(1)

简洁写法:

class Solution {
public:int findMin(vector<int>& nums) {int n = nums.size();int l = 0, r = n - 1;while (l < r) {int mid = l + r >> 1;if (nums[mid] > nums.back()) l = mid + 1;else r = mid;}return nums[l];}
};

注意特判:

这里的特判还是蛮坑的。关于 mid 有下面的几种写法:

  • nums[mid] >= nums[0]
  • nums[mid] < nums[0]
  • nums[mid] > nums[0] 这个是无解的。因为此时 mid 其实位于第一段中,且隐藏着 nums[mid]==nums[0] 这个条件。理论上应该让 l = mid + 1。但是一开始 mid=0 的情况下,nums[mid]=nums[0] == nums[0],就会走到 r = mid 这个逻辑里面去,但此时 r 不应该等于这个 nums[0] 这个非法值,它并不在答案所包含的区间内。
    • 故,这个写法,找不到最小的起始点。
    • 反而能找到最大的这个点。
    • 反例, [2, 1]。一开始 nums[mid]=nums[0]=2,如果 r=mid 的话,则造成了错误的区间更新。此时 l=r=0,就有问题了。
  • nums[mid] <= nums[0]
class Solution {
public:int findMin(vector<int>& nums) {if (nums.back() > nums[0]) return nums[0];int l = 0, r = nums.size() - 1;while (l < r){int mid = l + r >> 1;// 这里的等号必须要加上。因为 nums[0] 不是一个可选答案// 不能将 r=mid 包含 nums[0]if (nums[mid] >= nums[0]) l = mid + 1;  else r = mid;}return nums[l];}
};

这篇关于[M二分] lc153. 寻找旋转排序数组中的最小值(二分+边界情况+好题)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1110883

相关文章

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.

浅析CSS 中z - index属性的作用及在什么情况下会失效

《浅析CSS中z-index属性的作用及在什么情况下会失效》z-index属性用于控制元素的堆叠顺序,值越大,元素越显示在上层,它需要元素具有定位属性(如relative、absolute、fi... 目录1. z-index 属性的作用2. z-index 失效的情况2.1 元素没有定位属性2.2 元素处

查看Oracle数据库中UNDO表空间的使用情况(最新推荐)

《查看Oracle数据库中UNDO表空间的使用情况(最新推荐)》Oracle数据库中查看UNDO表空间使用情况的4种方法:DBA_TABLESPACES和DBA_DATA_FILES提供基本信息,V$... 目录1. 通过 DBjavascriptA_TABLESPACES 和 DBA_DATA_FILES

C++快速排序超详细讲解

《C++快速排序超详细讲解》快速排序是一种高效的排序算法,通过分治法将数组划分为两部分,递归排序,直到整个数组有序,通过代码解析和示例,详细解释了快速排序的工作原理和实现过程,需要的朋友可以参考下... 目录一、快速排序原理二、快速排序标准代码三、代码解析四、使用while循环的快速排序1.代码代码1.由快

Java中数组转换为列表的两种实现方式(超简单)

《Java中数组转换为列表的两种实现方式(超简单)》本文介绍了在Java中将数组转换为列表的两种常见方法使用Arrays.asList和Java8的StreamAPI,Arrays.asList方法简... 目录1. 使用Java Collections框架(Arrays.asList)1.1 示例代码1.

Go使用pprof进行CPU,内存和阻塞情况分析

《Go使用pprof进行CPU,内存和阻塞情况分析》Go语言提供了强大的pprof工具,用于分析CPU、内存、Goroutine阻塞等性能问题,帮助开发者优化程序,提高运行效率,下面我们就来深入了解下... 目录1. pprof 介绍2. 快速上手:启用 pprof3. CPU Profiling:分析 C

MySQL进阶之路索引失效的11种情况详析

《MySQL进阶之路索引失效的11种情况详析》:本文主要介绍MySQL查询优化中的11种常见情况,包括索引的使用和优化策略,通过这些策略,开发者可以显著提升查询性能,需要的朋友可以参考下... 目录前言图示1. 使用不等式操作符(!=, <, >)2. 使用 OR 连接多个条件3. 对索引字段进行计算操作4

C++一个数组赋值给另一个数组方式

《C++一个数组赋值给另一个数组方式》文章介绍了三种在C++中将一个数组赋值给另一个数组的方法:使用循环逐个元素赋值、使用标准库函数std::copy或std::memcpy以及使用标准库容器,每种方... 目录C++一个数组赋值给另一个数组循环遍历赋值使用标准库中的函数 std::copy 或 std::

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没