返回

前端刷题路-Day61:在排序数组中找到元素的第一个和最后一个位置(题号34)

前端

序言

前端开发是一门充满挑战和乐趣的领域,它需要我们不断学习和探索新的知识。算法和数据结构是前端开发的重要组成部分,掌握这些技能可以帮助我们编写更高效、更健壮的代码。LeetCode 是一个流行的在线算法题库,提供了许多经典的算法问题供我们练习和学习。

算法概述

二分查找法是一种高效的查找算法,适用于已排序的数组。它的基本思想是将数组分成两半,然后根据目标值与中间元素进行比较,以此来缩小查找范围。如果目标值大于中间元素,则在数组的后半部分继续查找;如果目标值小于中间元素,则在前半分部分继续查找。如此反复,直到找到目标值或确定目标值不存在于数组中。

实现细节

function findFirstAndLastPosition(arr, target) {
  // 检查数组是否为空或目标值是否有效
  if (!arr || arr.length === 0 || target === null) {
    return [-1, -1];
  }

  // 使用二分查找法找到目标值在数组中的第一个位置
  let firstIndex = findFirstIndex(arr, target);

  // 如果没有找到目标值,则返回 [-1, -1]
  if (firstIndex === -1) {
    return [-1, -1];
  }

  // 使用二分查找法找到目标值在数组中的最后一个位置
  let lastIndex = findLastIndex(arr, target);

  // 返回目标值在数组中的第一个和最后一个位置
  return [firstIndex, lastIndex];
}

function findFirstIndex(arr, target) {
  let low = 0;
  let high = arr.length - 1;

  // 使用二分查找法查找第一个位置
  while (low <= high) {
    let mid = Math.floor((low + high) / 2);
    if (arr[mid] === target) {
      // 如果找到目标值,则继续向前查找
      if (mid === 0 || arr[mid - 1] !== target) {
        return mid;
      } else {
        high = mid - 1;
      }
    } else if (arr[mid] < target) {
      low = mid + 1;
    } else {
      high = mid - 1;
    }
  }

  // 没有找到目标值,返回 -1
  return -1;
}

function findLastIndex(arr, target) {
  let low = 0;
  let high = arr.length - 1;

  // 使用二分查找法查找最后一个位置
  while (low <= high) {
    let mid = Math.floor((low + high) / 2);
    if (arr[mid] === target) {
      // 如果找到目标值,则继续向后查找
      if (mid === arr.length - 1 || arr[mid + 1] !== target) {
        return mid;
      } else {
        low = mid + 1;
      }
    } else if (arr[mid] < target) {
      low = mid + 1;
    } else {
      high = mid - 1;
    }
  }

  // 没有找到目标值,返回 -1
  return -1;
}

复杂度分析

二分查找法的平均时间复杂度为 O(log n),其中 n 是数组的长度。这是因为二分查找法在每次迭代中将数组的长度缩小一半,因此所需的时间与数组的长度成对数关系。

结语

二分查找法是一种高效的查找算法,在许多实际问题中都有着广泛的应用。通过这篇文章,我们介绍了如何使用二分查找法来解决一个排序数组中的查找问题。我们还提供了详细的代码示例和解释,帮助您理解算法的实现细节。希望这篇文章能够对您的前端开发学习和算法练习有所帮助。