使用二分法解决旋转数组的最小数字的问题

简介: 使用二分法解决旋转数组的最小数字的问题

旋转数组的最小数字


有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。

要求:空间复杂度:O(1)O(1) ,时间复杂度:O(logn)O(logn)

示例1:

输入:[3,4,5,1,2]

返回: 1

示例2:

输入:[3,100,200,3]

返回: 3


解题思路


暴力解法可以挨个遍历数组,寻找最小值,但是子题目要求:空间复杂度:O(1)O(1) ,时间复杂度:O(logn)O(logn),这就需要用一些技巧了

首先旋转数组将原本有序的数组分成了两部分有序的数组,因为在原始有序数组中,最小的元素一定是在首位,旋转后无序的点就是最小的数字。旋转后我们可以把数组分为AB两个区域,可以知道A区域所有的值都大于B区域

用两个指针,分别指向最左侧left和最右侧right,再获取一个中间指针mid;以区间[left,right]的最右侧的值为基准,使中间值与它比较;慢慢缩小区域,当left大于等于right时,就找到了最小值

具体步骤如下:

  • 第一步:初始化左右指针,双指针指向旋转后数组的首尾,作为区间端点。
  • 第二步:当左指针小于右指针则进入循环
  • 计算获取中间指针
  • 若是区间中点值小于区间右界值,则最小的数字一定在中点左边。 right = mid
  • 若是区间中点值大于区间右界值,则最小的数字一定在中点右边。left = mid+1
  • 若是区间中点值等于区间右界值,则是不容易分辨最小数字在哪半个区间,应该逐个缩减右界令right--
  • 第三步:当left大于等于right时,就找到了最小值,返回rotateArray[left]
function minNumberInRotateArray(rotateArray){
  let left = 0
  let right = rotateArray.length-1;
  while(left < right){
    let mid = Math.floor( (left + right)/2 );
    if(rotateArray[mid] < rotateArray[right]){
      right = mid;
    }else if(rotateArray[mid] > rotateArray[right]){
      left = mid+1;
    }else{
      right--;
    }
  }
  return rotateArray[left];
}


image.png


目录
相关文章
|
7月前
|
Java
【剑指offer】-旋转数组的最小数字-06/67
【剑指offer】-旋转数组的最小数字-06/67
|
7月前
|
算法 测试技术 C#
【单调栈】LeetCode2030:含特定字母的最小子序列
【单调栈】LeetCode2030:含特定字母的最小子序列
|
7月前
|
算法
算法题解-长度最小的子数组
算法题解-长度最小的子数组
剑指offer-10.旋转数组最小的数字
剑指offer-10.旋转数组最小的数字
62 0
旋转数组的最小数字
旋转数组的最小数字
49 0
每日一题——长度最小的子数组
每日一题——长度最小的子数组
|
算法
剑指offer 10. 旋转数组的最小数字
剑指offer 10. 旋转数组的最小数字
56 0
|
算法 Java
旋转数组的最小数字(剑指offer 11)
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
旋转数组的最小数字(剑指offer 11)
11.旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
90 0
11.旋转数组的最小数字
|
前端开发 测试技术 程序员
寻找旋转数组中的最小数字
寻找旋转数组中的最小数字
寻找旋转数组中的最小数字