题解 | #旋转数组的最小数字#

旋转数组的最小数字

http://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba

这道题花了蛮长的时间,明确知道使用二分法,但是在决策:什么时候当下的mid是最小值?选择左边还是右边?这两个最为纠结。
考虑两种情况:
一种是顺序的:[1, 2, 3, 4, 5, 6] 分成两部分[1, 2, 3] 4 [5, 6]
一种是翻转的:[6, 1, 2, 3, 4, 5] 分成两部分[6, 1, 2] 3 [4, 5]
可以看到,咱们虽然看不到区间内最小的值,例如[6, 1, 2]最小为1,但是6到2之间一定小于3,肯定包含比3小的数,例如2,所以选择端点小的区间就可以解决“选择左边还是右边”的问题。
[1, 2, 3]最小的端点是1,小于4;
[6, 1, 2]最小的端点是2,小于3;
那么同样的,如果mid的值小于左边也小于右边的值,则中间mid是最小的,直接返回。

上面的方式忽略掉了一个问题,踩到了最大的坑,就是重复值问题:
[5,1,2,2,2,3] 分拆为两部分:[5,1,2] 2 [2,3],这时候无论你选择直接返回2还是选择左右两边都是有问题的。
个人的做法是,在选择好mid值之后,分拆左右两边的时候会左右移动去除重复值,上述例子拆为[5,1] 2 [3]。
所以极限情况下会将时间复杂度为On。

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        if (array.length == 0) {
            return 0;
        }
        return find(array, 0, array.length - 1);
    }

    private int find(int []array, int begin, int end) {
        if (begin == end) {
            return array[begin];
        }
        int mid = (end + begin) / 2;
        int midValue = array[mid];

        int leftBegin = begin;
        int leftEnd = Math.max(begin, mid - 1);
        while(leftEnd - 1 >= begin) {
            if(array[leftEnd] == midValue) {
                leftEnd--;
            } else {
                break;
            }
        }
        int leftMin = Math.min(array[leftBegin], array[leftEnd]);

        int rightBegin = Math.min(end, mid + 1);
        while(rightBegin + 1 <= end) {
            if(array[rightBegin] == midValue) {
                rightBegin++;
            } else {
                break;
            }
        }
        int rightEnd = end;
        int rightMin = Math.min(array[rightBegin], array[rightEnd]);
        if (midValue < leftMin && midValue < rightMin) {
            return midValue;
        }
        if (leftMin < rightMin) {
            return find(array, leftBegin, leftEnd);
        } else {
            return find(array, rightBegin, rightEnd); 
        }      
    }
}
全部评论

相关推荐

KKorz:是这样的,还会定期默写抽查
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 春招至今,你的战绩如何? #
6127次浏览 57人参与
# 你的实习产出是真实的还是包装的? #
1240次浏览 29人参与
# MiniMax求职进展汇总 #
23157次浏览 300人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
7042次浏览 37人参与
# 简历第一个项目做什么 #
31297次浏览 315人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
186490次浏览 1115人参与
# 米连集团26产品管培生项目 #
4582次浏览 205人参与
# 研究所笔面经互助 #
118777次浏览 577人参与
# 面试紧张时你会有什么表现? #
30415次浏览 188人参与
# 简历中的项目经历要怎么写? #
309522次浏览 4162人参与
# 职能管理面试记录 #
10719次浏览 59人参与
# AI时代,哪些岗位最容易被淘汰 #
62625次浏览 743人参与
# 网易游戏笔试 #
6360次浏览 83人参与
# 把自己当AI,现在最消耗你token的问题是什么? #
6942次浏览 154人参与
# 腾讯音乐求职进展汇总 #
160420次浏览 1106人参与
# 从哪些方向判断这个offer值不值得去? #
56712次浏览 357人参与
# 正在春招的你,也参与了去年秋招吗? #
362702次浏览 2631人参与
# 你怎么看待AI面试 #
179383次浏览 1177人参与
# 小红书求职进展汇总 #
226874次浏览 1356人参与
# 你的房租占工资的比例是多少? #
92140次浏览 896人参与
# 校招笔试 #
467415次浏览 2952人参与
# 经纬恒润求职进展汇总 #
155705次浏览 1085人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务