​LeetCode刷题实战81:搜索旋转排序数组 II

Java实现 LeetCode 81 搜索旋转排序数组 II(二) 81. 搜索旋转排序数组 II 假设按照升序排序的数组在预先未知的某个点上进行了旋转。 ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。 编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。 示例 1: 输入: nums = [2,5,6,0,0,1,2], target = 0 输出: true 示例 2: 输... 阅读详情

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !

今天和大家聊的问题叫做 搜索旋转排序数组 II,我们先来看题面:

https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2]).

You are given a target value to search. If found in the array return true, otherwise return false.

题意

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。

编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。

样例

示例 1:

输入: nums = [2,5,6,0,0,1,2], target = 0
输出: true

示例 2:
输入: nums = [2,5,6,0,0,1,2], target = 3
输出: false

解题

https://www.cnblogs.com/techflow/p/13235840.html

如果是你按照顺序刷LeetCode的话,你会发现我们在之前做过一道非常相似的题目。它就是LeetCode的33题,Search in Rotated Sorted ArrayI。不过不同的是,在33题的题意当中,明确表明了数组当中的元素是不包含重复元素的,除此之外,这两题的题意完全一样。

LeetCode 33,在不满足二分的数组内使用二分的方法

这么一点小小的差别会带来解法的变化吗?

题解

答案当然是肯定的,不然出题人可以退休了。

问题是,问题出在哪里呢?

我们先不着急,先来回忆一下33题中的做法。我们当时使用了一个最简单的笨办法,就是先通过二分法找到数组截断的位置。然后再通过截断的位置还原出原数组的情况,根据我们target的大小,找到它可能存在的位置。

但是在当前这个问题当中,这个思路走不通了。走不通的原因也很简单,就是因为重复元素的存在。

举个例子:[1, 3, 1, 1, 1, 1, 1, 1]

当我们进行二分查找的时候,发现mid是1和left的1相等,我们根本无法判断截断点究竟在mid的左侧还是右侧,二分查找也就无从谈起了。

我们当然可以退一步采用遍历的方法去寻找切分点,但是既然如此,我们为什么不直接去寻找答案呢?反正都已经是O(n)的复杂度了。所以这是行不通的,我们想要使得复杂度维持在就必须要寻找其他的路数。

思路和解法很多时候不是凭空来的,需要我们对问题进行深入的分析。在这个问题当中,我们的问题是明确并且简单的。就是一个调换了部分顺序的有序数组,只是我们不确定的是调换的部分究竟有多长。由于我们最终希望通过二分法来寻找答案,所以我们可以根据调换的元素是否过半想出两种情况来。

我把这两种情况用图展示出来:

也就是说我们的分割点可能在数组的前半段也可能在后半段,对于这两种情况我们的处理方法是不同的。

我们先看第一种情况,数组的前半段是有序的,后半段存在截断。如果target的范围在前半段当中,我们可以抛弃掉后半段,直接在前半段中进行二分。否则,我们需要舍弃前半段,在后半段当中重复这个过程。我们可以把后半段看成是一个全新的问题,也一样可以分成两种情况,类似于递归一样的往下执行即可。

再来看第二种情况,第二种情况的后半段和第一种情况的前半段是一样的,都是有序的元素,我们直接二分即可。它的前半段和第一种情况的后半段是一样的,我们没法判断,需要继续二分。

也就是说,我们只能在有序的数组进行二分,如果当前数组存在分段,不是整体有序的,那我们就对它进行拆分。拆分之后总能找到有序的部分,如果还找不到就继续拆分。因为分段点只有一个,所以不论当前的数组什么样,拆分一次之后,必然至少可以找到一段是有序的。

想明白这点之后就简单了,看起来很像是递归,但实际上它的本质仍然是二分。代码并不难写,但是还有一个问题没解决,就是当nums[m] = nums[l]的时候,我们如何判断是哪一种情况呢?

答案是没法判断,两种情况都有可能,对于这种情况也没有很好的办法,我想出来的办法是可以将l向右移动一位,相当于抛弃了一个最左侧的数。我们把这些思路总结总结,代码也就出来了:

class Solution:
    def search(self, nums: List[int], target: int) -> bool:
        l, r = 0, len(nums)-1
        while l <= r:
            m = (l + r) >> 1
            if nums[m] == target:
                return True
            
            if nums[l] == nums[m]:
                l += 1
                continue
                
            if nums[l] < nums[m]:
                if nums[l] <= target < nums[m]:
                    r = m - 1
                else:
                    l = m + 1
            else:
                if nums[m] < target <= nums[r]:
                    l = m + 1
                else:
                    r = m - 1
        return False

总结

到这里,我们关于这道题的题解就结束了。在问题的最后,出题人给我们留了一个问题,和33题比起来,这题的解法的时间复杂度会有变化吗?

表面上看我们一样用到了二分,所以同样是log级的复杂度,问题的复杂度并没有变化。但实际上并不是这样的,我们来看一种最坏的情况,假设数组当中所有的值全部相等。这个时候二分就不起效果了,最终会退化成O(n)的线性枚举,这样又变成了O(n)的复杂度。当然,在大部分情况下,这并不会发生。所以是算法的最坏复杂度退化成了O(n),平均复杂度依然是O(logN)。

好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力。

上期推文:

LeetCode40-60题汇总,速度收藏!

LeetCode刷题实战61:旋转链表

LeetCode刷题实战62:不同路径

LeetCode刷题实战63:不同路径 II

LeetCode刷题实战64:最小路径和

LeetCode刷题实战66:加一

LeetCode刷题实战67:二进制求和

LeetCode刷题实战68:文本左右对齐

LeetCode刷题实战69:x 的平方根

LeetCode刷题实战70:爬楼梯

LeetCode刷题实战71:简化路径

LeetCode刷题实战72:编辑距离

LeetCode刷题实战73:矩阵置零

LeetCode刷题实战74:搜索二维矩阵

LeetCode刷题实战75:颜色分类

LeetCode刷题实战76:最小覆盖子串

LeetCode刷题实战77:组合

LeetCode刷题实战78:子集

LeetCode刷题实战79:单词搜索

【中等】力扣算法题解析LeetCode81:搜索旋转排序数组 II 题目要求在旋转后的非降序数组中查找目标值,数组可能包含重复元素。核心思路是二分查找,但需处理重复元素干扰。通过判断有序区间(左半或右半)并调整搜索范围,时间复杂度最优为 O(log n),最坏情况(全重复)为 O(n)。代码实现中处理了重复元素,确保正确缩小搜索范围。示例输入验证了算法的正确性,如 nums = [2,5,6,0,0,1,2] 查找 target = 0 返回 true,查找 3 则返回 false。 阅读详情

相关推荐

LeetCode 第81题:搜索旋转排序数组 II

通过上述详细的解析和多种解法的对比,相信大家对LeetCode第81题的解法有了深入的理解。本文介绍了线性搜索法、二分查找法和改进的二分查找法,每一种方法都有其优缺点。线性搜索法虽然简单直接,但效率较低;二分查找法利用了数组的有序特性,提高了搜索效率;改进的二分查找法在处理数组中存在重复元素的情况下更加鲁棒。希望大家能够根据具体情况选择合适的解法,并灵活应用到其他类似的搜索问题中。最后,希望大家在刷题的过程中,不断总结,不断进步。祝大家都能在算法的道路上走得更远!

Gemini的博客 313

Leetcode(81)——搜索旋转排序数组 II

Leetcode(81)——搜索旋转排序数组 II

KCDCY的博客 414

Java使用easyExcel生成excel文件直接写入邮件附件并发送

1.引入pom依赖 <!-- email --> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency> <!-- easyexcel需要依赖poi jar包 --> <depe

weixin_50493320的博客 3910

【LeetCode每日一题】81. 搜索旋转排序数组 II

【LeetCode每日一题】81. 搜索旋转排序数组 II题目:已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同。在传递给函数之前,nums 在预先未知的某个下标 k...

Francis的博客 398

项目过程记录:ADS-B信号接收并显示(Ubuntu20.04+ANTSDR E310V2)

最近被安排做一个ADS-B信号接收的项目,拿到软件无线电模块(ANTSDR E310V2)后安装环境和软件真的太折磨了。。在此记录以下我走过的弯路,大家可以参考一下。

weixin_43627638的博客 5018

跟着团子学SAP CO:揭秘结果分析码在项目结算中的实战应用(一)KKA2/CJ88

本文深入解析了SAP CO模块中结果分析码在项目结算中的核心作用。以KKA2(方法10)和事务代码CJ88为例,详细阐述了如何在项目完工后一次性确认收入的场景下,通过结果分析功能实现收入与成本的精准匹配,将项目成本暂估为在制品,确保各期利润的准确反映。

gamma的博客 686

leetcode:81. 搜索旋转排序数组 II

本题元素不唯一,这意味着我们无法直接根据nums[0]的大小关系,将数组分为为两段,即无法通过「二分」来找到旋转点。因为「二分」的本质是二段性,并非单调性。只要一段满足某个性质,另外一段不满足某个性质,就可以用「二分」。我们知道,所谓的旋转其实就是「将某个下标前面的所有数整体移到后面,使得数组从整体有序变为分段有序」。的扩展,区别在于本题有重复元素。......

OceanStar的博客 296

FastGPT 引申:借鉴 FastGPT 基于MySQL + ES 实现知识库(含表结构以及核心代码)

FastGPT 引申:借鉴 FastGPT 基于MySQL + ES 实现知识库(含表结构以及核心代码)

蜗牛的专栏 3435

[算法] leetcode顺序表相关题目详解

目录1. leetcode 203.移除数组元素解法一解法二2. leetcode 26. 删除有序数组中的重复项解法3. leetcode88. 合并两个有序数组解法一解法二(推荐)4. 189. 旋转数组解法一解法二5. 989. 数组形式的整数加法解法 1. leetcode 203.移除数组元素 /*203. 移除数组元素 * 示例 1: 输入:nums = [3,2,2,3], val = 3 输出:2, nums = [2,2] 解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素

weixin_43717520的博客 535

【中兴交换机MC-LAG配置】

​ 中兴mc-lag配置 主设备配置如下: Keepalive链路 interface smartgroup1023 //用作MC-LAG的Keepalive链路接口 switch attribute disable yes description For_Keepalived exit interface xgei-0/1/1/47 switch attribute disable yes description For_Keepalived exit interface

qq_31440733的博客 1万+

华为OD机试真题2025双机位C卷 C++ 实现【卡牌游戏】

小明正在尝试一种新的牌游戏。游戏规则只如下:首先,小明拿到一张写有数字m的牌。 然后,他会拿到另外n张牌,上面分别写有不同的数字,牌排成一排。小明的目标是从这排牌中找到一串连续的牌,这些牌上数字的总和可以被 m整除。你的任务是判断小明是否可以完成这个目标。

MISAYAONE的博客 281

LeetCode 搜索旋转排序数组II

假设按照升序排序的数组在预先未知的某个点上进行了旋转。 ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。 编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。 示例 1: 输入: nums = [2,5,6,0,0,1,2], target = 0 输出: true 示例 2: 输入: nums = [2,5,...

hestyle的博客 612

11、RK3566/3568 Android11切割屏幕 长条屏 显示

在使用 RK3566 平台进行 Android 11 开发时,遇到切割屏(长条屏)显示画面不全。本文将详细介绍如何配置,以及如何修改 HWComposer 来调整显示区域,解决图像缩放问题。我这边屏幕是lvds接口的,分辨率1920 1080实际的屏物理尺寸是1920x463。

qq_39451352的博客 252

leetcode数组汇总_LeetCode刷题实战81:搜索旋转排序数组 II

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !今天和大家聊的问题叫做搜索旋转排序数组 II,我们先来看题面:https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/Su...

weixin_39844880的博客 93

【系统架构设计师】二十三、通信系统架构设计理论与实践①

通信网络主要形式:局域网、广域网、移动通信网。 局域网网络架构有 4 种类型:单核心架构、双核心架构、环型架构、层次型架构。 广域网属于多级网络,通常由骨干网、分布网、接入网组成。在网络规模较小时,可仅由骨干网和接入网组成。通常,在大型网络构建中,通过广域网将分布在各地域的局域网互连起来,形成一个大的网络。 移动通信网为移动互联网提供了强有力的支持,尤其是5G 网络为个人用户、垂直行业等 提供了多样化的服务。

帅次的博客 3764

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

调换数组元素的顺序_LeetCode刷题实战81:搜索旋转排序数组 II

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !今天和大家聊的问题叫做搜索旋转排序数组 II,我们先来看题面:https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/Su...

weixin_36058835的博客 196

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

LeetCode第81题_搜索旋转排序数组II

已知存在一个按非降序排列的整数数组nums,数组中的值不必互不相同。在传递给函数之前,nums在预先未知的某个下标k)上进行了旋转,使数组变为(下标从 0 开始计数)。例如,在下标5处经旋转后可能变为。给你旋转后的数组nums和一个整数target,请你编写一个函数来判断给定的目标值是否存在于数组中。如果nums中存在这个目标值target,则返回true,否则返回false。你必须尽可能减少整个操作步骤。

qq_40263592的博客 1152

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

【LeetCode: 81. 搜索旋转排序数组 II + 二分查找】

【LeetCode: 81. 搜索旋转排序数组 II + 二分查找】已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同。给你 旋转后 的数组 nums 和一个整数 target ,请你编写一个函数来判断给定的目标值是否存在于数组中。如果 nums 中存在这个目标值 target ,则返回 true ,否则返回 false 。

Coder_ljw的博客 1369

Python描述 LeetCode 81. 搜索旋转排序数组 II

Python描述 LeetCode 81. 搜索旋转排序数组 II   大家好,我叫亓官劼(qí guān jié ),在GitHub & 优快云中记录学习的点滴历程,时光荏苒,未来可期,加油~博主目前仅在GitHub & 优快云中写博客,唯一博客更新的地址为:亓官劼的博客 ,近期将逐渐同步刷题相关记录到GitHub:[Algorithmic-learning-records] (https://github.com/qiguanjie/Algorithmic-learning-r

一起加油 1249

LeetCode 题目 81:搜索旋转排序数组 II

多种算法详解 LeetCode 题目 81:搜索旋转排序数组 II

10年数据\经营分析经验,现任大厂数据分析负责人 832

Leetcode 81. 搜索旋转排序数组 II C++

Leetcode 81. 搜索旋转排序数组 II 题目 假设按照升序排序的数组在预先未知的某个点上进行了旋转。 ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。 编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。 测试样例 1. 输入: nums = [2,5,6,0,0,1,2], target = 0 输出: true 2. 输入: nums = [2,5,6,0,0,1,2], target = 3 输出: fa

weixin_43750513的博客 303

leetcode81.搜索旋转排序数组 II

https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii 假设按照升序排序的数组在预先未知的某个点上进行了旋转。 ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。 编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。 示例 1: 输入: ...

ShawDa's Blog 1649

81. 搜索旋转排序数组 II

题目 81. 搜索旋转排序数组 II 题解 代码 public class code81 { // public static boolean search(int[] nums, int target) { // for (int i = 0; i < nums.length; i++) { // if (nums[i] == target) { /...

dev_zyx的博客 471

Leetcode 81. 搜索旋转排序数组 II

对于这种情况,我们只能将当前二分区间的左边界加一,右边界减一,然后在新区间上继续二分查找。对于数组中有重复元素的情况,二分查找时可能会有。这题的不同在于有重复元素,需要多一步操作。,首次二分时无法判断区间。

JehanRio's Private Blog 212
上一篇: 一个技术总监的忠告:精通那么多技术,你为何还是受不到重用?
下一篇: MyBatis 的工作原理,你了解过吗?
编程IT圈
博客等级 码龄6年 1130粉丝 544原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值