Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >每天一道leetcode154-寻找旋转排序数组(有重复数字)中的最小值

每天一道leetcode154-寻找旋转排序数组(有重复数字)中的最小值

作者头像
乔戈里
发布于 2019-09-17 03:33:09
发布于 2019-09-17 03:33:09
58300
代码可运行
举报
文章被收录于专栏:Java那些事Java那些事
运行总次数:0
代码可运行

前言

今天的题目是寻找旋转排序数组(有重复数字)中的最小值 II,这道题目是在之前做过的这道题目的升级版,这是上一道题目。

每天一道leetcode-153

今天的题目是在上一道题目的基础上加了有重复数字这一条件,本次的题目是在上一次题目的基础上进行。

题目

leetcode-154 寻找旋转排序数组(有重复数字)中的最小值 II

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

难度:hard;

英文链接:

https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/

中文链接:

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

题目详述

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

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

请找出其中最小的元素。

注意数组中可能存在重复的元素。

示例 1:

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

示例 2:

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

题目详解

思路

由于之前已经有了在不包含重复数字的代码,所以我想着尝试在这个代码的基础上,进行改进,直到成功AC。

第一次尝试

直接把上次在153题中的代码进行了提交,如果不懂下面的代码可以看我的这篇文章。

果然没有AC。

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

这里的话,因为有重复数字,所以我把27行中else代表着nums[mid]<nums[0]的情况,而由于有重复数字,所以nums[mid]与nums[0]的情况应该分开讨论,单独列出来;

第二次尝试

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

如上述代码所示,增加了29行代码到31行代码,就是处理的nums[mid] 与nums[0]相等情况,由于当二者相等的时候,情况复杂,所以这个时候使用left++的方式去缩小查找的范围。

第三次尝试

上述代码,提交了以后,依然无法通过,下图中可以看出,这个测试用例没有过去,所以我就分析,自己手动地去跑一边代码,一开始left=0,right=5所以mid=2;

因为nums[mid]<nums[0],所以可以看出来,nums[mid]是在旋转数组的后半段,进入到代码28行,right=mid-1,所以right=1;left=0;mid=0;

所以nums[mid]=nums[0],所以left++,left=1,right=1,mid=1,所以nums[mid]<nums[0].进入28行,right--,right=0,由于left>right,所以循环结束。

这个时候,我发现了,在靠近nums[0]的nums[1]的这个位置有可能是最小值,但是我的代码没有考虑到,类似的nums[nums.length-1]这个地方,靠近它的数组的前一个元素nums[nums.length-2]这个地方,也有可能是最小值,所以我在代码把这两种情况考虑了进去。如下述代码,33-40行代码就是我把刚才的两种情况考虑了进去。

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

第四次尝试

上述代码提交以后,下图所示,还是没AC。

然后我根据上图显示,发现还有一种情况没有考虑进行,那就是最小值,出现在了中间的搜索过程中,所以我在上述代码中,在中间进行判断的过程中,把可能的最小值保存了下来。

下面代码中的27-28行代码,31-32行代码,35-36行代码,就是我把这种情况考虑了进去,保存中间可能出现的最小值。

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

        if(min > nums[nums.length-1])
            min = nums[nums.length-1];
        if(min > nums[1])
            min = nums[1];
        if(min > nums[nums.length-2])
            min = nums[nums.length-2];
        return min;
    }
}

上述代码一提交,最终AC了。

结束语

罗马不是一日建成的,可以看到我这道题的AC过程,一步步地把没有考虑到的情况加入到我们的代码中,最后所有的情况考虑到了,那么自然也就能AC了。要学会使用错误用例来推敲问题到底出现在哪了,然后凭借着自己的死磕硬生生地把每一道题的代码都自己靠自己的努力去把它AC掉,不管写的多烂但起码是自己写的,这个就是我们编程的基本功的积累,当然如果超过半天都做不出来还是网上找找答案吧~

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

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

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

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
每天一道leetcode-33
目前准备每天刷一道题leetcode的题目,以此来激励那些零基础入门的人,千万不要被什么科班和非科班的说法吓倒了,计算机这个行业只要你肯努力,没有什么逾越不了的鸿沟。
乔戈里
2019/09/17
2830
每天一道leetcode-33
​LeetCode刷题实战153:寻找旋转排序数组中的最小值
https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/
程序员小猿
2021/01/19
3020
(Leetcode 2021 刷题计划) 154. 寻找旋转排序数组中的最小值 II
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7] 在变化后可能得到:
windism
2021/04/10
2830
【优选算法】专题三:二分查找(二)
xxxflower
2024/01/09
1200
【优选算法】专题三:二分查找(二)
漫画:知乎面试题(旋转数组最小值Ⅱ - 进阶版)
今天是小浩算法“365刷题计划”第72天。继续为大家讲解二分法系列篇 - 旋转排序数组最小值Ⅱ(进阶版)。话不多说,直接看题:
程序员小浩
2020/03/30
6390
漫画:知乎面试题(旋转数组最小值Ⅱ - 进阶版)
【手绘漫画】图解LeetCode之寻找旋转排序数组中的最小值 II(LeetCode154题)
今天是第二期,争取每天一期,最多两天一期,欢迎大家监督我。。。公众号监督最好!!!
我是管小亮
2020/04/20
3060
【手绘漫画】图解LeetCode之寻找旋转排序数组中的最小值(LeetCode153题)
文章首发于本人CSDN账号:https://blog.csdn.net/tefuirnever
我是管小亮
2020/04/20
3350
【LeetCode每日一题】154. 寻找旋转排序数组中的最小值 II
今日题目154题,每日一题微信交流群可以点击右下角:合作转载->联系我,备注:刷题,拉你入群。
公众号guangcity
2021/04/22
3760
(Leetcode 2021 刷题计划) 153. 寻找旋转排序数组中的最小值
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
windism
2021/04/08
2480
【数据结构与算法】二分查找
https://leetcode.cn/problems/binary-search/
风中的云彩
2025/05/13
1180
【数据结构与算法】二分查找
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
6810
亚马逊面试题--寻找旋转排序数组中的最小值系列
已知一个长度为 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]
程序员小熊
2021/05/28
3540
亚马逊面试题--寻找旋转排序数组中的最小值系列
☆打卡算法☆LeetCode 154. 寻找旋转排序数组中的最小值 II 算法解析
“给定一个数组,按照升序排列,经过1-n次旋转后,得到输入数组,找出数组中最小元素。”
恬静的小魔龙
2022/08/07
2750
☆打卡算法☆LeetCode 154. 寻找旋转排序数组中的最小值 II 算法解析
LintCode 寻找旋转排序数组中的最小值 II题目分析代码
假设一个旋转排序的数组其起始位置是未知的(比如0 1 2 4 5 6 7 可能变成是4 5 6 7 0 1 2)。
desperate633
2018/08/22
4230
漫画:知乎面试题(旋转数组最小值Ⅰ - 基础版)
今天是小浩算法“365刷题计划”第71天。继续为大家讲解二分查找,分享一道知乎面试题。话不多说,直接看题。
程序员小浩
2020/03/30
6290
漫画:知乎面试题(旋转数组最小值Ⅰ - 基础版)
【leetcode刷题】T9-寻找旋转排序数组中的最小值
今天分享leetcode第9篇文章,也是leetcode第153题—寻找旋转排序数组中的最小值,地址是:https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/
木又AI帮
2019/07/18
4280
【leetcode刷题】T9-寻找旋转排序数组中的最小值
刷完这19道leetcode二分查找算法,不信进不了大厂
对于二分题,其实就是设定一个中间值 mid, 然后通过这个值进行一个判断 check(mid), 通过这个函数的返回值,判断将不可能的一半剪切掉;
hellocoder2028
2022/11/10
5050
力扣刷题(数组篇)
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 (leetcode-cn.com)  小王的主页:(14条消息) 学好c语言的小王同学的博客_CSDN博客-领域博主 小王的gitee:比特王信哲 (bitewang) - Gitee.com
王同学要努力
2022/12/20
2480
力扣刷题(数组篇)
【算法刷题指南】二分查找
南桥
2025/02/07
760
153. 寻找旋转排序数组中的最小值
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
早起的鸟儿有虫吃
2023/03/28
7970
153. 寻找旋转排序数组中的最小值
推荐阅读
相关推荐
每天一道leetcode-33
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验