『力扣题解』搜索旋转排序数组

75 阅读1分钟

数组在旋转后,保持局部有序的状态,比如说[4, 5, 6, 7, 0, 1, 2, 3],l=0, r= 7, mid=3,nums[l] < nums[m],说明左半部分[4, 5, 6, 7]是有序的,右半部分[7, 0, 1, 2, 3]是无序的。

  1. 为了应用二分查找,优先去有序的那一半,需要将nums[m]和nums[l]进行比较。
  2. 如果能确认nums[m] < target <= nums[r]nums[l] <= target < nums[m],按照二分查找的逻辑设置l和r即可,[l, m - 1]或[m + 1, r]。
  3. 否则,说明target不在该区间中,如果不在左半区间,l = m + 1;如果不在右半区间,r = m - 1。
  4. 把2和3结合起来,完成if-else的逻辑。
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var search = function (nums, target) {
  let l = 0;
  let r = nums.length - 1;

  while (l <= r) {
    const m = Math.floor((l + r) / 2);

    if (nums[m] === target) return m;
    // 左半边为递增区间
    // 此处的等号是必须的,因为m可能等于l,比如[3,1],l = m = 0, r = 1
    // 此时[l,m]是递增区间,如果认为[m,r]是递增区间,就错了
    if (nums[m] >= nums[l]) {
      if (target >= nums[l] && target < nums[m]) {
        r = m - 1;
      } else {
        // target不在该区间内; 二分查找,target单纯比nums[m]大
        l = m + 1;
      }
    }
    // 右半边为递增区间
    else {
      if (target <= nums[r] && target > nums[m]) {
        l = m + 1;
      } else {
        // target不在该区间内; 二分查找,target单纯比nums[m]小
        r = m - 1;
      }
    }
  }
  return -1;
};