Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >每天一道leetcode-81

每天一道leetcode-81

作者头像
乔戈里
发布于 2019-09-17 06:24:18
发布于 2019-09-17 06:24:18
38800
举报
文章被收录于专栏:Java那些事Java那些事
运行总次数:0

前言

目前准备每天刷一道题leetcode的题目,以此来激励那些零基础入门的人,千万不要被什么科班和非科班的说法吓倒了,计算机这个行业只要你肯努力,没有什么逾越不了的鸿沟。

只要你肯努力,一份努力,一份汗水,在程序员这个职业,你的每一份付出都会得到对应的那一份汇报,尊重学习规律,循序渐进,别想着一口吃个胖子,罗马也不是一天建成的,有朝一日,你终会变成你想成为的人。

题目目前可能需要一定的算法与数据结构基础才能看懂,后序会写一下零基础也能看懂的入门知识,然后就可以看懂我编写的题目了~

案例

题目

leetcode-81 在有重复数字的有序数组中寻找n

tag(分类): 二分查找这一类

链接:

https://leetcode.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:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输入: nums = [2,5,6,0,0,1,2], target = 0输出: true

示例 2:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输入: nums = [2,5,6,0,0,1,2], target = 3输出: false

进阶:

  • 这是 搜索旋转排序数组 的延伸题目,本题中的 nums 可能包含重复元素。
  • 这会影响到程序的时间复杂度吗?会有怎样的影响,为什么?

题解

先上代码~

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    public boolean search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while(left <= right)
        {
            int mid = left + (right-left)/2;
            if(nums[mid] == target || nums[left] == target || target == nums[right])
                return true;
            if(nums[mid] > nums[left])
            {
                if(target > nums[mid])
                     left = mid + 1;
                else{
                    if(target > nums[left])
                        right = mid - 1;
                    else
                        left = mid + 1;
                }
            }else if(nums[mid] < nums[left])
            {
                if(target < nums[mid])
                    right = mid -1;
                else{
                    if(target > nums[left])
                        right = mid - 1;
                    else
                        left = mid + 1;
                }
            }else{
                left++;//right--;
            }
        }
        return false;
    }
}

上一篇题目:每天一道leetcode-33

本道题目是对上一篇题目的加强版,在有序数组的中加入了有重复数字这一条件,题目变得稍微难了一些些,思路也是很类似的,就是分情况讨论。

对于这种题目,数组,有序这两个字眼结合起来,就是要第一时间考虑到二分查找。

先举个例子,假设有旋转数组[3,3,3,4,5,6,1,2,3,3],以图形化的方式表示出这个数组,3,3,3,4,5,6为前半段,1,2,3,4为后半段,后续的图不是这个数组。

思路:由于无法确定target,nums[mid]谁大谁小,以及target和nums[mid]到底在前半段,还是在后一段,不同的情况下,对于令left = mid+1还是right = mid-1是不一样的情况,所以这里分情况进行讨论,把所有的情况讨论一遍,然后就知道,到底是变化left还是变化right,进而去缩小这个区间,找到我们要找到的数,在这里唯一不同的就是多了一种nums[mid]与nums[left]如果相等了的情况,该怎么处理。

nums[mid] >nums[left]

第10行,nums[mid]>nums[left]判断为真,说明nums[mid]在前半段。如下图所示

target>nums[mid]

紧接着到了12行,target>nums[mid],看图得知,target只能是在前半段。

所以观察得知,令left=mid+1往target去逼近。

target<nums[mid]

当12行代码判断为假,也就是要进入到14行。

而target小于nums[mid]时候,由于不知道target是在前半段还是后半段,所以的分情况讨论。

target<nums[mid]且target在前半段

当target在前半段,也就是代码第15行,target>nums[left],如下图所示。

观察图可知,16行,明显应该令right=mid-1,right减小去往target逼近。

target<nums[mid]且target在后半段

当target在后半段,也就是代码15行判断为假,也就是nums[left]>target,进入到18行。

观察图可知,明显应该是left=mid+1,来往target去逼近。

到这,10-20行代码解读完毕。

nums[mid]<nums[left]

当第10行代码判断为假,也就是nums[mid]<nums[left],nums[mid]落入到后半段,此时进入到代码21这个分支。如下图所示。

由于不知道target与nums[mid]的关系得分情况讨论。

target<nums[mid]

当target<nums[mid]时候,也就22行代码,观察上图得知,target只能在后半段,如下图所示。

明显应该是right=mid-1,来逼近taeget. ,23行代码所示。

target>nums[mid]

当22行代码判断为假,进入到25行代码,也就是target大于nums[mid]。

当target大于nums[mid]的时候,target可以在前半段大于nums[mid],也可以在后半段大于nums[mid],所以得分两种情况讨论。

target>nums[mid]且target在前半段

target在前半段,也就是代码25行,target>nums[mid]

如上图所示,明显令right=mid-1去逼近target,也就是代码26行。

target>nums[mid]且target在后半段

target在后半段,也就是代码25行判断为假,target<nums[left],进入到28行.

观察图得知,left=mid+1;

nums[mid]=nums[left]

当着二者相等的时候,无法讨论,这是为啥呢?

这里举个例子,帮助大家理解。

对于数组

[3,3,3,3,4,5,6,7],nums[mid]=nums[left]对吧,这时候如果要找6,target=6,那么应该是left=mid+1;往6去逼近。

而对于数组

[3,3,3,3,4,5,6,7,1,2,3,3,3,3,3,3,3,3,3,3,3,3],nums[mid]=nums[left]也是相等的对吧,但是这是候去找6,就应该是right=mid-1,去逼近这个6。

所以对于这种nums[mid]=nums[left]的情况你无法去确定nums[mid]是在前半段还是后半段没所以也就无法讨论。

所以只能是一次移动一个去逼近target,也就是代码31行,left++;或者right--都可以去去逼近target。

结束语

总体来说思路与leetcode31这道理差不多,但是多了一个nums[mid]=nums[left]的情况,把这个情况单独拿出来谈论即可。

END

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-10-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员乔戈里 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
​LeetCode刷题实战81:搜索旋转排序数组 II
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
程序员小猿
2021/01/20
5050
​LeetCode刷题实战81:搜索旋转排序数组 II
33. Search in Rotated Sorted Array
https://leetcode.com/problems/search-in-rotated-sorted-array/
翎野君
2023/05/12
2000
LeetCode 81,在不满足二分的数组内使用二分法 II
今天是LeetCode专题第50篇文章,我们来聊聊LeetCode中的81题Search in Rotated Sorted ArrayII。
TechFlow-承志
2020/07/02
1.2K0
剑指 offer代码解析——面试题38数字在排序数组中出现的次数
题目:统计一个有序数组中K出现的次数。 分析:本题最直观的思路就是遍历数组,统计K出现的次数即可。 这种方式的时间复杂度为O(n)。下面我们充分利用“有序数组”这一条件,提高算法的时间效率。 对于一个有序数组,所有的数字K一定都集中在一起,因此只要我们找到这一组K的头和尾就能知道K出现的次数。 此时问题就转化为:在一个有序数组中寻找某个数字。 我们很自然地就想到了二分搜索,在目前所有的搜索算法中,二分搜索具有最高的搜索效率。 对于本题,我们需要进行两次二分搜索,一次寻找K的头,一次寻找K的尾。
大闲人柴毛毛
2018/03/09
6840
LeetCode<二分搜索> 33 & 81 Search in Rotated Sorted Array I&II
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
大学里的混子
2018/10/30
7070
每天一道leetcode154-寻找旋转排序数组(有重复数字)中的最小值
今天的题目是寻找旋转排序数组(有重复数字)中的最小值 II,这道题目是在之前做过的这道题目的升级版,这是上一道题目。
乔戈里
2019/09/17
6470
每天一道leetcode154-寻找旋转排序数组(有重复数字)中的最小值
乐视2017暑假实习生笔试题二分查找之JAVA实现
试题 对一个含有20个元素的有序数组做二分查找,数组起始下标为1,则查找A[2]的比较序列的下标为() A. 9,5,4,2 B. 10, 5, 3, 2 C. 9, 6, 2 D. 20, 10, 5, 3, 2 解析 没错,可能懂的人一眼就瞧出来了,选B;不懂的百度也能搜出来。当然网上也有不同的声音,有些童鞋感觉答案不对,在求指教!计算得出的是{10,5,2}。 吓得我赶紧百度了一下百度百科(尽管有时候也挺扯淡的),百度百科给出的demo是: 假如有一组数为3,12,24,36,55,68,75,8
小柒2012
2018/04/13
6270
认知算法(三)
努力是为了不平庸~ 算法学习有些时候是枯燥的,这一次,让我们先人一步,趣学算法!欢迎记录下你的那些努力时刻(算法学习知识点/算法题解/遇到的算法bug/等等),在分享的同时加深对于算法的理解,同时吸收他人的奇思妙想,一起见证技术er的成长~
异星球的小怪同志
2022/11/20
3530
认知算法(三)
一网打尽!二分查找解题模版与题型全面解析
二分查找算是最为基本的一个算法,也比较容易掌握。但是有些时候,我们可能因为一些细节的点没有考虑全而程序出错。
五分钟学算法
2019/08/16
9820
一网打尽!二分查找解题模版与题型全面解析
每天一道leetcode-35 搜索插入的位置
目前准备每天刷一道题leetcode的题目,以此来激励那些零基础入门的人,千万不要被什么科班和非科班的说法吓倒了,计算机这个行业只要你肯努力,没有什么逾越不了的鸿沟。
乔戈里
2019/09/17
3040
每天一道leetcode-35 搜索插入的位置
leetcode-33-搜索旋转排序数组
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
chenjx85
2018/08/16
4440
面试中如果这样写二分查找!
这里我只需要5次就成功猜出来了,这就是二分查找的思想,每一次猜测,我们都选取一段整数范围的中位数,根据条件帮我们逐步缩小范围,每一次都以让剩下的选择范围缩小一半,效率提高。
Golang梦工厂
2022/07/11
2610
面试中如果这样写二分查找!
【手绘漫画】图解LeetCode之搜索旋转排序数组(LeetCode33题),二分查找
排序,旋转,不重复,没错,就是我,【手绘漫画】图解LeetCode之寻找旋转排序数组中的最小值(LeetCode153题)大声喊到。
我是管小亮
2020/04/20
4500
【刷穿 LeetCode】33. 搜索旋转排序数组(中等)
例如, [0,1,2,4,5,6,7] 经旋转后可能变为 [4,5,6,7,0,1,2] 。
宫水三叶的刷题日记
2021/02/20
3120
高频手撕算法合集来了!
基础数据结构的融合是成为庞大系统的基石。比如 Redis 中的跳跃表,数据库索引B+树等,只有对基础的数据结构足够的熟悉才能更容易去理解稍微复杂的结构,就仿佛我们闯关打怪一样,一步一步解锁直到结局。
帅地
2020/09/28
8370
高频手撕算法合集来了!
每天一道剑指offer-数字在排序数组中出现的次数
每天一道剑指offer-数字在排序数组中出现的次数 https://www.nowcoder.com/practice/70610bf967994b22bb1c26f9ae901fa2?tpId=13
乔戈里
2019/01/07
3690
19道leetcode二分查找算法
对于二分题,其实就是设定一个中间值 mid, 然后通过这个值进行一个判断 check(mid), 通过这个函数的返回值,判断将不可能的一半剪切掉;
hellocoder2028
2022/12/13
3620
二分查找团灭力扣旋转排序数组系列
Leetcode 中有一系列旋转排序数组相关的问题,例如33. 搜索旋转排序数组、81. 搜索旋转排序数组 II、153. 寻找旋转排序数组中的最小值、154. 寻找旋转排序数组中的最小值 II 和面试题10.03 搜索旋转数组等,本文介绍通过二分查找团灭这一系列问题,供大家参考,希望能对大家有所帮助。
程序员小熊
2021/05/28
6620
二分查找团灭力扣旋转排序数组系列
六十七、二分查找算法及其四个变形问题
算法:当数据量很大适宜采用该方法。采用二分法查找时,数据需是「有序不重复」的。二分法查找本质上就是分治算法。
润森
2022/08/17
7960
六十七、二分查找算法及其四个变形问题
剑指 offer——面试题8求旋转数组的最小值
题目:将一个非递减序列的某一处切一刀,再把前半段序列放到后半段序列的后面,这样组成的新序列叫做“旋转数组”。要求获取一个旋转数组的最小值。 这本质上是一个求最值的问题,最简单的方法就是顺序遍历数组,从中找出最小值,该方法的时间复杂度为O(n)。但这种方法会被面试官鄙视的,所以我们寻找更为高效的办法。 这道题给的数组是一个“旋转数组”,旋转数组是将一个非递减数组切成两个数组后重新组装而成的,旋转数组的前半段所有元素值均大于等于后半段元素的值,两段的分界点就是最小值。 要寻找分界点,可以采用对半搜索,若第一个元
大闲人柴毛毛
2018/03/09
1.1K0
相关推荐
​LeetCode刷题实战81:搜索旋转排序数组 II
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档