leetcode 困难 —— 寻找旋转排序数组中的最小值 I,II(二分 + 特判)

news/2025/1/8 19:54:26/

先说寻找旋转排序数组中的最小值 I

题目:
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。
给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

题解:
这个比较简单,比如 4 5 6 1 2 3
那么我们二分查找,即可找到
二分的判断条件为 是否小于 nums[0] 的值
l 设为 0,r 设为 nums.size() - 1,是一个左开右闭区间(不包括第一个值)
如果 nums[mid] 小于 nums[0],则 r = mid(包括 mid)
如果 nums[mid] 大于 nums[0],则 l = mid(不包括 mid)

注意还要加上,如果 1 2 3 4 5,则我们找的范围不包括第一个值,所以会错过 1
所以最后的结果,需要和 nums[0] 比较,取最小值

代码如下

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

再说寻找旋转排序数组中的最小值 II

题目:
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,4]
若旋转 7 次,则可以得到 [0,1,4,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。
给你一个可能存在 重复 元素值的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
你必须尽可能减少整个过程的操作步骤。

题解:
第一次看到这种考虑的不是最坏情况的算法题,想错解法了

这种题,肯定不能用二分
如果 4 4 4 0 4 4 4 4 4 4 4 4,我怎么找到这个最小值
二分的话,需要可以判断来缩小下一次寻找范围
这个 nums[mid] 为 4 的话,得不到任何消息
所以如果考虑这种特殊情况的话,那肯定复杂度为 O(n),需要遍历一次

但是题目的意思是,尽可能的优化,那应该怎么考虑呢
尽可能的用二分,并对特殊情况进行特判
比如之前题目中

if(nums[mid] > nums[0]) {l = mid;
}
else if(nums[mid] < nums[0]) {r = mid;
}

需要对等于的情况进行特判,比如 4 x x x x 4 x x x x 4
我们肯定是要缩小范围的,但是呢,又只能一个一个减小范围(不然可能会漏掉)
怎么一个一个缩小呢,可以比较如果两边边界,如果等于 nums[mid],则可以向左或者向右移动一个,缩小边界

代码如下

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

http://www.ppmy.cn/news/40496.html

相关文章

【MySQL】实验八 触发器与存储过程

文章目录 1. 创建商品价格修改记录表2. 创建触发器,当更改商品价格(price列)时,记录价格3. SQL触发器:插入新员工时,同步更新部门表相应人数4. SQL触发器:删除学生数据5. SQL触发器:创建成绩表插入触发器6. SQL存储过程:查询订单7. SQL存储过程:建立存储过程,查询课程…

paddle实现波士顿房价预测任务

要点&#xff1a; 参考官方案例飞桨PaddlePaddle-源于产业实践的开源深度学习平台 1 加载飞桨框架的相关类库 #加载飞桨、NumPy和相关类库 import paddle from paddle.nn import Linear import paddle.nn.functional as F import numpy as np import os import random 飞桨支…

Navicat连接数据库出现 is not allowed to connect to this MySQL server 报错

1.本地连接Linux服务器的mysql出现报错&#xff0c;如下&#xff1a; 2.问题原因 我们发现防火墙已经关闭了&#xff0c;还会出现这样的情况&#xff0c;那是因为mysql数据只允许自身所在的本机器连接&#xff0c;不允许进行远程连接 3.解决方式 &#xff08;1&#xff09;在…

java审计-XXE

介绍 XXE就是XML外部实体注入。当允许引用外部实体 时&#xff0c;通过构造恶意内容&#xff0c;就可能导致任意文件读取、系统命令执 行、内网端口探测、攻击内网网站等危害。 XXE支持sun.net.www.protocol 里的所有协议&#xff1a;http&#xff0c;https&#xff0c; file&…

第一部分——简单句——第二章——简单句的核心——第二节 成分角度的扩展非谓语动词作定语、状语

什么是非谓语动词 一主搭配一谓&#xff08;正如中国的一夫一妻制&#xff09;但早在封建社会时期&#xff0c;地主家里比较有钱。 再往里面加上谓语&#xff0c;就需要降半级&#xff0c;也就是非谓语动词。 什么时候用非谓语动词 一主搭配一谓后&#xff0c;还需要使用动词…

初识设计模式 - 命令模式

简介 命令设计模式&#xff08;Command Design Pattern&#xff09;可以将请求发送者和接收者完全解耦。发送者和接收者之间没有直接引用关系&#xff0c;发送请求的对象只需要知道如何发送请求&#xff0c;而不必知道如何完成请求。 其定义是&#xff0c;将请求&#xff08;…

常用异常检测模型的应用

常用异常检测模型的应用 描述 异常数据检测不仅仅可以帮助我们提高数据质量&#xff0c;同时在一些实际业务中&#xff0c;异常数据往往包含有价值的信息&#xff0c;如异常交易、网络攻击、工业品缺陷等&#xff0c;因此异常检测也是数据挖掘的重要手段。常用的异常检测模型…

spring 概述

正常的三层架构违背了OCP开闭原则&#xff0c;DIP依赖倒置原则 OCP核心原则为:只要你在扩展系统功能的时候&#xff0c;没有修改过以前写好的代码&#xff0c;就负责OCP原则&#xff0c;反之&#xff0c;如果在扩展系统功能的时候&#xff0c;修改了&#xff0c;则这个设计是失…