剑指offer--旋转数组的最小数字

题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

解法分析

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        if(array == null || array.length == 0)
            return 0;
        int p1 = 0, p2 = array.length-1;
        //也可以使用二分查找
        //p1指向前面的排序数组,p2指向后面的排序数组
        //如果数组本身就有序(旋转0个元素),直接返回mid的值
        int mid = p1;
        while(p1 < p2 && array[p1] >= array[p2]) {
            if(p2 - p1 == 1) {
                mid = p2;
                break;
            }
            
            mid = p1 + (p2 - p1) / 2;
            //特殊情况:p1, mid, p2三者相等
            if(array[p1] == array[mid] && array[p2] == array[mid]) {
                //顺序查找
                int res = array[p1];
                for(int i=p1+1; i<=p2; i++) {
                    res = Math.min(res, array[i]);
                }
                return res;
            }
            //判断当前mid是否位于前面的排序数组中
            if(array[mid] >= array[p1]){
                p1 = mid;
            } else if(array[mid] <= array[p2]) {
                p2 = mid;
            }
        }
        
        return array[mid];
    }
 }

解法一为直接遍历数组找最小值,虽然复杂度为O(n),但并没有利用题目中所说的排序数组的条件(虽然是旋转的排序数组).想到排序数组的查找应该就是二分查找了,这道题是变种的二分查找。

具体解法为:

1)两个指针p1, p2分别指向数组的起始和结束位置(和普通的二分查找一样)

2)中间元素:这里需要考虑如何根据和中间元素的比较来缩小查找的范围,普通的二分查找直接比较就好了。观察这里的数组,排序数组被分为了两部分:前半部分(旋转的)和后半部分,若中间元素mid大于等于p1,则mid一定在前半部分的排序数组,这时可以将p1移到mid的位置:p1=mid。同理,若mid小于等于p2,则p2=mid。最后p1指向的是前半部分的最后一个元素,p2指向的是后半部分的第一个元素(即最小元素)

例子:3 4 5 1 2

需要注意的特殊情况:

1)数组可能旋转了0个元素(即没有旋转)

2)p1、mid、p2三者指向的元素相等,即无法判断中间的数字是位于前面的子数组还是后面的子数组,从而无法移动指针缩小查找范围。这时不得不采用顺序查找的方法。

例子:1 0 1 1 1 和1 1 1 0 1

(加阴影的为旋转的)

参考剑指offer题解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值