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

本文介绍了一种在旋转数组中查找最小值的有效方法。通过改进的二分搜索算法,能够快速定位旋转点并找到最小元素。针对不同情况,如数组是否包含重复元素,提供了具体的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
思路:
1. 数组中不包含重复元素,例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。那么我们可以采用二分搜索的改进版本实现。
2. 若数组的长度为0,则返回0。初始化三个指针left, right和mid,left指向数组的第一个元素,right指向数组的最后一个元素,mid初始化为0。因为数组是经过旋转的,此时旋转可能造成两种情况。第一种情况是:旋转位置为0,则相当于没有进行过旋转,且数组中不包含重复元素,若数组的长度为1,则会发生array[left] == array[right]的情况;另一种情况是:旋转的位置不为0,对于数组中没有重复的元素,则left指向左侧序列,right指向右侧序列,有array[left] > array[right]。
3. 若right - left = 1,此时right指向的就是旋转数组的最小元素,则返回array[right],结束循环。
4. 令mid = left + (right - left) / 2,则若array[mid] > array[left],则mid指向的元素左侧是有序的,旋转数组的最小值肯定在array[mid]的右侧,此时left = mid。
5. 若array[mid] < array[right],此时array[mid]的右侧是有序的,旋转数组的最小值肯定在array[mid]的左侧,此时right = mid;
6. 若数组没有被旋转,因为mid的初始值为0,直接返回第一个元素array[mid]。
7. 若数组中有重复元素,比如对数组{0, 1, 1, 1, 1, 1}进行旋转则会得到{1, 1, 0 ,1, 1}。令poi = 0,逐个遍历数组,寻找当array[i + 1] < array[i] 时的旋转数组最小值,若不存在这种情况,返回array[poi],即第一个元素。

public class Solution {
    //若数组中包含重复元素,则进行逐个遍历
    public int getPoi(int[] array){
        int poi = 0;
        if(array.length == 1){
            return array[0];
        }
        for(int i = 0; i < array.length; i++){
            if(array[i + 1] < array[i]){
                poi = array[i + 1];
                break;
            }
        }
        return poi;   
    }

    public int minNumberInRotateArray(int [] array) {
        if(array.length == 0){
            return 0;
        }
        int left = 0;
        int right = array.length - 1;
        int mid = 0;
        /**若数组中没有重复的元素,left在左侧序列,right在右侧序列,
            若数组反转位置%array.length != 0,则必有array[left] > array[right],左侧序列元素大于右侧序列元素
           若数组中有重复元素,则可能会发生array[left] == array[right]。
        **/
        while(array[left] >= array[right]){
            if(right - left == 1){
                return array[right];
            }
            mid = left + (right - left)/2;
            //array数组中有重复元素,逐个遍历
            if(array[mid] == array[left] && array[mid] == array[right]){
               getPoi(array);
            }
            //若array[mid] >= array[left],则mid的左侧是有序的,最小值在右侧;
            //若array[mid] = array[left],可能有两种情况,1. mid = left 2.数组中有重复元素
            if(array[mid] >= array[left]){
                left = mid;
            }
            //mid的右侧是有序的,最小值在左侧
            if(array[mid] <= array[right]){
                right = mid;
            }
        }
        //若数组是单调递增的,则返回第一个元素
        return array[mid];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值