11. 旋转数组的最小数字(剑指 Offer 题解Java版)

11. 旋转数组的最小数字

题目描述

        把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
在这里插入图片描述

题目链接

NowCoder

解题思路

        将旋转数组对半分可以得到一个包含最小元素的新旋转数组,以及一个非递减排序的数组。新的旋转数组的数组元素是原数组的一半,从而将问题规模减少了一半,这种折半性质的算法的时间复杂度为 O(logN)(为了方便,这里将 log2N 写为 logN)。
在这里插入图片描述
        此时问题的关键在于确定对半分得到的两个数组哪一个是旋转数组,哪一个是非递减数组。我们很容易知道非递减数组的第一个元素一定小于等于最后一个元素。

        通过修改二分查找算法进行求解(l 代表 low,m 代表 mid,h 代表 high):

        1.当 nums[m] <= nums[h] 时,表示 [m, h] 区间内的数组是非递减数组,[l, m] 区间内的数组是旋转数组,此时令 h = m;
        2.否则 [m + 1, h] 区间内的数组是旋转数组,令 l = m + 1。

可以借助下图理解过程

在这里插入图片描述

代码

package 旋转数组的最小数字;
/*
作者     :XiangLin
创建时间 :05/03/2020 22:15
文件     :MINNUMBER.java
IDE      :IntelliJ IDEA
*/

public class MINNUMBER {
    public int minNumberInRotateArray(int[] nums){
        if (nums.length == 0){
            return 0;
        }
        int l = 0;int h = nums.length - 1;
        while (l < h){
            int m = l + (h - l) / 2;
            if (nums[l] == nums[m] && nums[m] == nums[h]){
                return minNumber(nums,l,h);
            }
            else if (nums[m] <= nums[h]){
                h = m;
            }
            else
                l = m + 1;
        }
        return nums[l];
    }
    private int minNumber(int[] nums ,int l ,int h){
        for (int i = l; i < h; i++){
            if (nums[i] > nums[i+1]){
                return nums[i+1];
            }
        }
        return nums[l];
    }
    public static void main(String[] args) {
        MINNUMBER nira = new MINNUMBER();
        int nums[] = {1,1,0,1};
        int n = nira.minNumberInRotateArray(nums);
        System.out.println(n);
    }
}

在这里插入图片描述
        如果数组元素允许重复,会出现一个特殊的情况:nums[l] == nums[m] == nums[h],此时无法确定解在哪个区间,需要切换到顺序查找。例如对于数组 {1,1,1,0,1},l、m 和 h 指向的数都为 1,此时无法知道最小数字 0 在哪个区间。

package 旋转数组的最小数字;
/*
作者     :XiangLin
创建时间 :05/03/2020 22:15
文件     :MINNUMBER.java
IDE      :IntelliJ IDEA
*/

public class MINNUMBER {
    public int minNumberInRotateArray(int[] nums){
        if (nums.length == 0){
            return 0;
        }
        int l = 0;int h = nums.length - 1;
        while (l < h){
            int m = l + (h - l) / 2;
            if (nums[l] == nums[m] && nums[m] == nums[h]){
                return minNumber(nums,l,h);
            }
            else if (nums[m] <= nums[h]){
                h = m;
            }
            else
                l = m + 1;
        }
        return nums[l];
    }
    private int minNumber(int[] nums ,int l ,int h){
        for (int i = l; i < h; i++){
            if (nums[i] > nums[i+1]){
                return nums[i+1];
            }
        }
        return nums[l];
    }
    public static void main(String[] args) {
        MINNUMBER nira = new MINNUMBER();
        int nums[] = {1,1,0,1};
        int n = nira.minNumberInRotateArray(nums);
        System.out.println(n);
    }
}

在这里插入图片描述
在这里插入图片描述

毕业后计划 my future plan
Everybody dreams about the future.There are many things waiting for us in the future,and sometimes I can’t wait to become an adult.I’m excited about my future because I have big hopes and dreams.

每个人都对未来抱有梦想。在未来有很多事情等待着我们,有时,我迫不及待地想成为成年人。我对自己的未来感到很兴奋因为我有很大的希望和梦想。

Here’s what I want to do.I plan to study hard bacause I want to go to a school overseas.My dream school is Harvard University.I might be a teacher,a doctor or a scientist.No matter what,I’ll be an expert at what I do so i can be useful to society.I want to be rich,too.I want to make a lot of money so my family will be proud of me.I also like to travel,so I want to visit every country and see the world.I hope to meet many people and make many friends.

这就是我想做的事情。我打算努力学习,因为我想去国外上学。哈佛大学是的我理想学校。我可能成为一个教师,医生或科学家。不管怎样,我会在我所工作的领域成为一个专家,这样我才可以对社会有用。我想是富裕。我想赚很多钱,我的家人会为我感到骄傲。我也喜欢旅游,所以我想访问的每一个国家并看看这个世界。我希望能与许多人成为朋友。

I am determined to make my dreams come true.I know it won’t be easy,but when I do make my dreams come true,I’ll be the happiest person in the world.

我下定决心让我的梦想成真。我知道这不容易,但当我实现我的梦想时我将会是世界上最幸福的人。
在这里插入图片描述
个人微信公众号,专注于学习资源、笔记分享,欢迎关注。我们一起成长,一起学习。一直纯真着,善良着,温情地热爱生活,,如果觉得有点用的话,请不要吝啬你手中点赞的权力,谢谢我亲爱的读者朋友
五角钱的程序员,专注于学习资源、笔记分享。
XiangLin
2020年3月6日于重庆城口
好好学习,天天向上,终有所获

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值