剑指Offer:旋转数组的最小数字

KEY:

如果面设题是要求在排序的数组(或者部分排序的数组)中查找一个数字或者统计某个数字出现的次数,那么我们都可以尝试使用二分法

转自力扣:
方法一:二分法
只要是一次可以排除一半,都可以用二分法。那么如何使用二分法呢?我们很自然会想到使用边界的值和中间位置的值进行比较。

注意:这里的提法是“中间数”,即位于中间的那个数,不是中位数,请注意区分。

可以分为以下两种情况:

1、中间数与左边界比较

尝试在纸上写出几个例子:

例 1:[1, 2, 3, 4, 5]

例 2:[2, 3, 4, 5, 1]

以上这两个例子,中间数都比左边界大,但是旋转排序数组的最小值可能在中间数的左边(例 1),也可能在中间数的右边(例 2),因此不能使用中间数与左边界比较作为二分法的讨论依据。

接下来,看看另一种讨论依据。

2、中间数与右边界比较:

(1)当中间数比右边界表示的数大的时候,中间数就一定不是目标数(旋转排序数组的最小值)。

还是尝试举个例子:

例 3:[7, 8, 9, 10, 11, 12, 1, 2, 3]

中间数 11 比右边界 3 大,因此中间数以及中间数前面的数都不是目标数,把左边界设置中间数位置 + 1,即 left = mid + 1;

(2)当中间数比右边界表示的数小的时候,中间数就可能是目标数(旋转排序数组的最小值),举个例子:

例 4:[7, 8, 1, 2, 3]

中间数 1 比右边界表示的数小的时候,说明,中间数到右边界是递增的(对于这道题是非递减),那么中间数右边的(不包括中间数)就一定不是目标数,可以把它们排除,不过中间数有可能是目标数,就如本例,因此,把右边界设置为 right = mid。

(3)当中间数与右边界表示的数相等的时候,看下面两个例子:

例 5:[0, 1, 1, 1, 1, 1, 1]

例 6:[1, 1, 1, 1, 0, 1, 1]

目标值可能在中间数的左边,也可能在中间数的右边,那么该怎么办呢?很简单,此时你看到的是右边界,就把只右边界排除掉就好了。正是因为右边界和中间数相等,你去掉了右边界,中间数还在,就让中间数在后面的循环中被发现吧。

因此,根据中间数和右边界的大小关系,可以使用二分法搜索到目标值。

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/solution/er-fen-fa-fen-zhi-fa-python-dai-ma-by-liweiwei1419/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

思考: 如果中间数大于最右面的数 说明最小的数在中间数和最右面数之间,因为数组是排完序的 最左边的元素肯定大于最右边的数

package Arrays;

public class s6 {
    public static void main(String[] args) {
        int[] arr = new int[]{1,1,1,1,0,1};
        System.out.println(s6.minNumberInRotateArray(arr));
    }


    public static int minNumberInRotateArray(int[] array) {

        if (array == null || array.length == 0) return 0;
        int left = 0;
        int right = array.length - 1;

        while (left < right) {
            int mid = (left + right) / 2;
            if (array[mid] > array[right]) {
                left = mid + 1;
            } else if (array[mid] == array[right]) {
                right--;

            } else if (array[mid] < array[right]){
                right = mid;
            }
        }
        
            return array[left];
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值