剑指 offer11. 旋转数组的最小数字 -- 二分查找

二分查找的思想是:

  1. 从数组的中间位置开始,如果中间元素正好是目标元素,则结束搜索;
  2. 如果目标值大于或小于中间元素,则在大于或小于中间元素的那一半数组中搜索;
  3. 重复1、2步;若未找到,return -1;

二分查找用在有序数组中。
二分查找的使用场景:查找一个数字;统计某个数字出现的次数。

分而治之是算法设计中的一种方法。它将一个问题分成多个和原问题相似的小问题,递归解决小问题,再将结果合并以解决原来的问题。分而治之适用的场景:归并、快速、二分和反转二叉树。

题目要求

在这里插入图片描述

题目分析

题目中给出的是半有序数组,仍然可以用二分查找。那中间元素和左、右哪个位置比较呢?
比如:[1,2,3,4,5] 和 [3,4,5,1,2],中间位置都比左位置元素大,第一个数组最小位置在左边,第二个在右边,所以跟左边比较得不出答案。但是跟右位置比较,第一个数组可以得出在左边,第二个在右半边。所以,用中间位置元素和右位置元素比较。

步骤

  • 设置左右位置元素;
  • 中间位置元素依次和右边元素位置对比;
  • 中间位置元素小于右边元素,区间为[ left,mid ];
  • 中间位置元素大于右边元素,区间为[ mid+1,high ];
  • 中间元素和最右边元素相同,只能把最右边排出掉,区间为[ high-- ]。

Code part

var minArray = function(numbers) {
  if(!numbers.length) return 0;
  let low = 0;
  let high = numbers.length - 1;

  while(low < high){
    const mid = Math.floor((low + high) / 2); //注意mid的位置,求每次移动后的mid位置,所以在while里面
    if(numbers[mid] > numbers[high]){ 
        //说明最小元素在mid右边,且mid元素比最右边大
        //所以下一轮搜索区间为[mid+1,right]
        low = mid + 1;
      }else if(numbers[mid] < numbers[high]){ 
        //mid 右边的元素一定不是最小数字,mid有可能是,
        //所以下一轮搜索区间为[low,mid]
        high = mid;
      }else{ 
        //中间元素和最右边元素相同,只能把最右边排出掉,
        //下一轮搜索区间为[left,high-1]
        high--
      }
  }
  return numbers[low]//最小数字一定在数组中,不管low,high如何移动,每动一次,low永远是区间内最小数字
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值