返回

LeetCode 34:有序数组中目标元素的首次和末次出现位置

前端

前言

在计算机科学中,二分查找是一种高效的搜索算法,用于在排序数组中查找特定元素。它的时间复杂度为 O(log n),其中 n 是数组的长度。在本文中,我们将探讨如何使用二分查找算法在有序数组中找到给定目标元素的首次和末次出现位置。

算法步骤

  1. 初始化

    • 将数组的左右边界设置为 left = 0 和 right = n - 1,其中 n 是数组的长度。
  2. 循环

    • 计算数组中间索引 mid = (left + right) // 2。
    • 比较目标元素 target 与 nums[mid]:
      • 如果 target < nums[mid],则将 right = mid - 1。
      • 如果 target > nums[mid],则将 left = mid + 1。
      • 如果 target = nums[mid],则更新 first 和 last 指针来标记首次和末次出现位置。
  3. 更新边界

    • 如果 left > right,则表示找不到目标元素,返回 -1。
    • 如果找到目标元素,则根据 first 和 last 指针继续向左右扩展搜索范围,直到找到首次和末次出现位置。

代码示例

Python

def find_first_and_last(nums, target):
  left, right = 0, len(nums) - 1
  first, last = -1, -1

  while left <= right:
    mid = (left + right) // 2

    if nums[mid] < target:
      left = mid + 1
    elif nums[mid] > target:
      right = mid - 1
    else:
      # 找到目标元素,更新首次和末次出现位置
      first = mid
      last = mid

      # 向左扩展搜索范围,找到首次出现位置
      while first >= 0 and nums[first] == target:
        first -= 1

      # 向右扩展搜索范围,找到末次出现位置
      while last < len(nums) and nums[last] == target:
        last += 1

      break

  return first, last

Java

public class Solution {
    public int[] searchRange(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        int first = -1, last = -1;

        while (left <= right) {
            int mid = (left + right) / 2;

            if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1;
            } else {
                first = mid;
                last = mid;

                while (first >= 0 && nums[first] == target) {
                    first--;
                }

                while (last < nums.length && nums[last] == target) {
                    last++;
                }

                break;
            }
        }

        return new int[]{first, last};
    }
}

C++

vector<int> searchRange(vector<int>& nums, int target) {
  int left = 0, right = nums.size() - 1;
  int first = -1, last = -1;

  while (left <= right) {
    int mid = (left + right) / 2;

    if (nums[mid] < target) {
      left = mid + 1;
    } else if (nums[mid] > target) {
      right = mid - 1;
    } else {
      first = mid;
      last = mid;

      while (first >= 0 && nums[first] == target) {
        first--;
      }

      while (last < nums.size() && nums[last] == target) {
        last++;
      }

      break;
    }
  }

  return {first, last};
}

时间复杂度

二分查找算法的时间复杂度为 O(log n),其中 n 是数组的长度。这是因为在每次迭代中,我们都可以将搜索范围减半,从而有效地缩小搜索空间。

结论

使用二分查找算法在有序数组中查找目标元素的首次和末次出现位置是一种高效的方法,其时间复杂度为 O(log n)。通过遵循本文中概述的步骤和代码示例,您可以轻松地实现此算法并将其应用于实际问题中。通过掌握这种技术,您将能够提高您在解决此类问题时的效率和准确性。