旋转数组的最小数字

37 篇文章 0 订阅
23 篇文章 0 订阅

题目: 把一个数组最

旋转数组的特点:

(1)递增排序的数组旋转之后的数组可划分为两个排序的子数组;

(2)前面的子数组的元素都大于或等于后面子数组的元素;

(3)最小的元素刚好是两个子数组的分界线;

(4)旋转数组在一定程度上是有序的;

在有序的数组中可以用二分查找实现O(logn)的查找,我们也可用二分查找的思想寻找旋转数组的最小数字。

思路:
1. 设置两个指针,初始状态第一个指针指向前面子数组的第一个元素,第二个指针指向后面子数组的最后一个元素
2. 找到两个指针的中间元素;
3.若其大于等于第一个指针指向的元素,则说明其在前面的子数组中,且显然最小元素在中间元素的右边,若其小于等于第二个指针指向的元素,则说明其在后面的子数组中,且显然最小元素在中间元素的左边

如此,便可以缩小搜索范围,减少时间复杂度,最终第一个指针指向前面子数组的最后一个元素,而第二个指针指向后面子数组的第一个元素,它们处于相邻位置,而第二个指针指向的刚好是最小的元素。

注意:当两个指针指向的数字及它们中间的数字三者相等时,无法判断中间数字位于前面的子数组还是后面的子数组,也就无法移动两个指针来缩小查找的范围,此时只能用顺序查找的方法。

例如:数组{1,0,1,1,1}和数组{1,1,1,0,1}都可看成是递增数组{0,1,1,1,1}的旋转。第一种情况,中间数字位于后面的子数组,第二种情况,中间数字位于前面的子数组。
(5)按旋转规则,第一个元素应该是大于或等于最后一个元素的;

但也有特例:若把排序数组的前0个元素搬到最后面,及排序数组本身,仍是数组的一个旋转,此时数组中的第一个数字是最小的数字。

public class ReverseMinNumber08 {
    public int search(int[] nums){
        int len =nums.length;
        if(nums==null|| len<=0)
            return Integer.MAX_VALUE;
        int st=0;   //首部
        int etd = len-1; //末尾
        //如果数组为空则返回
        //使用二分法查找
        //最终第一个指针指向前面子数组的最后一个元素,而第二个指针会指向后面子数组的第一个元素,也就是它们最终会指向两个相邻的元素,而第二个指针指向的刚好是最小的元素
        while(etd-st!=1){
            int mid = (st +etd)/2;
            //若中间元素大于首部元素(说明是在前面的递增子数组中),则说明,最小的元素应该在后半部分,此时将指向首部的st指向中间位置
            if(nums[mid]>nums[st]){
                st=mid;
            }else if(nums[mid]<nums[etd]){
                //若中间元素小于首部元素(说明是在后面的递增子数组中),则说明,最小的元素应该在前半部分,此时将指向尾部的etd指向中间位置
                etd=mid;
            }
            //当st,etd,mid所指位置元素都相等时,无法判断,则需要使用顺序查找的方法
            else if(nums[st]==nums[mid] && nums[etd]==nums[mid]) {
                return setpSearch(nums);
            }
        }


        return nums[etd];
    }
    //顺序查找
    public int setpSearch(int[] nums){
        int len = nums.length;

        int result = nums[0];
        for(int i=0;i<len;i++){

            if(nums[i]<result){
                result = nums[i];
                break;
            }
        }   
        return result;
    }
    public static void main(String[] args) {
        int [] nums = new int []{5,6,2,4};
        int [] nums2 = new int[]{1,0,1,1,1};
        int [] nums3 =new int[]{1,1,1,0,1};
        int [] nums4 = new int[]{0,0,1,1,1};
        ReverseMinNumber08 r = new ReverseMinNumber08();
        System.out.println(r.search(nums));
        System.out.println(r.search(nums2));
        System.out.println(r.search(nums3));
        System.out.println(r.search(nums4));
    }

}

Result:

2
0
0
0

参考:
C++版本:
http://blog.csdn.net/htyurencaotang/article/details/9385995

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值