二分法查找旋转数组的元素

149 阅读1分钟

说明

一种在有序数组中查找某一特定元素的搜索算法,搜索过程从数组的中间元素开始。

搜索过程

1、 如果中间元素正好是要查找的元素,则搜索过程结束

2、如果特定元素大于或者小于中间元素,则在数组大于或者小于中间的元素的那一半中查找,而且跟开始一样从中间元素开始比较

3、如果在某一步骤数组为空,则代表找不到。

注意

使用二分法的先决条件是有序数组,表达式使用 L + (R - L)/2 更合适

实现

function binarySearch(arr, key) {
  let left = 0;
  let right = arr.length - 1;
  while (left <= right) {
    let mid = left + parseInt((right - left) / 2)
    if (arr[mid] == key) {
      return mid;
    } else if (arr[mid] > key) {
      right = mid - 1;
    } else if (arr[mid] < key) {
      left = mid + 1;
    }
  }
  return -1;
}

变种查询

1、查找第一个或最后一个与target相等的元素

function getEqualKey(arr, target) {
  let option = binarySearch(arr, target);
  if (option < 0) return [-1, -1];
  else {
    let left = option - 1,
      right = option + 1;
    while (left >= 0 && arr[left] == target) left--;
    while (right < arr.length && arr[right] == target) right++;
    return [left + 1, right - 1];
  }
}

2、查找最后一个小于target/第一个大于target的元素

function getAdjoinKey(arr, target) {
  let option = binarySearch(arr, target);
  if (option < 0) return [-1, -1];
  else {
    let left = option - 1,
      right = option + 1;
    while (left >= 0 && arr[left] == target) left--;
    while (right < arr.length && arr[right] == target) right++;
    if (right >= arr.length) right = -1;
    return [left, right];
  }
}

3、数组的旋转(局部有序):[4, 5, 6, 1, 2, 3]

function binaryPartSearch(arr, key) {
  let left = 0;
  let right = arr.length - 1;
  while (left != right) {
    let mid = left + parseInt((right - left) / 2);
    if (arr[mid] == key) return mid; // 中位数相等直接返回
    // 分两种情况:1.中分位左边都是有序的 2.左边有一部分是局部有序的
    if (arr[left] < arr[mid]) {
      // 数组左边第一位小于key并且中分位大于key,则key在左边,把right重新赋值
      // 否则,key在右边,把left重新赋值
      if (arr[left] <= key && arr[mid] > key) {
        right = mid - 1;
      } else {
        left = mid + 1;
      }
    } else {
      // 局部有序
      // 数组最后一位的值大于key,并且中分位小于key,则key在右边,把left重新赋值
      if (arr[right] >= key && arr[mid] < key) {
        left = mid + 1;
      } else {
        right = mid - 1;
      }
    }
  }
  if (arr[left] == key) return left;
  return -1;
}