返回

LeetCode:在旋转的数组中找到目标值

前端

旋转数组中的目标值查找:算法指南

旋转数组的定义

旋转数组是指将一个数组中的元素向左或向右移动一定数量的单位,使其形成一个新的数组。例如,将数组 [1, 2, 3, 4, 5] 向左移动两个单位,得到新的数组 [3, 4, 5, 1, 2]。

算法实现

在旋转数组中查找目标值时,二分查找算法变得更加复杂。以下是改进后的算法步骤:

  1. 找到数组的最小值: 通过二分查找算法找到数组中最小值的索引,该值将作为数组的起点。
  2. 将数组分为两部分: 以最小值索引为分界点,将数组分为左右两部分。
  3. 分别在两部分中进行二分查找: 分别在左右两部分中使用标准的二分查找算法查找目标值。
  4. 返回目标值的下标: 如果在任一部分中找到目标值,则返回其下标,否则返回 -1。

示例代码(Python):

def find_target_in_rotated_array(nums, target):
    """
    在旋转数组中查找目标值

    Args:
        nums: 旋转数组
        target: 目标值

    Returns:
        目标值的下标,如果没有找到,返回 -1
    """

    # 找到数组的最小值
    min_index = find_min_index(nums)

    # 将数组分为两部分
    left_part = nums[min_index:]
    right_part = nums[:min_index]

    # 在两部分中分别进行二分查找
    left_index = binary_search(left_part, target)
    right_index = binary_search(right_part, target)

    # 返回目标值的下标
    if left_index != -1:
        return left_index + min_index
    elif right_index != -1:
        return right_index
    else:
        return -1

def find_min_index(nums):
    """
    找到旋转数组的最小值

    Args:
        nums: 旋转数组

    Returns:
        最小值的下标
    """

    left = 0
    right = len(nums) - 1

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

        if nums[mid] > nums[right]:
            left = mid + 1
        else:
            right = mid

    return left

def binary_search(nums, target):
    """
    在有序数组中进行二分查找

    Args:
        nums: 有序数组
        target: 目标值

    Returns:
        目标值的下标,如果没有找到,返回 -1
    """

    left = 0
    right = len(nums) - 1

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

        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    return -1

总结

通过将旋转数组分成两部分并分别应用二分查找算法,我们可以有效地在旋转数组中查找目标值。这种算法具有较好的时间复杂度,为 O(log n),其中 n 是数组的长度。

常见问题解答

  1. 为什么在旋转数组中不能直接使用二分查找算法?
    因为旋转数组中不存在有序区间,无法直接应用二分查找算法。

  2. 算法中如何找到旋转数组的最小值?
    通过二分查找算法,比较数组中相邻元素的值,将最小值移动到数组的起点。

  3. 如何将旋转数组分为两部分?
    以最小值索引为分界点,数组的一部分位于其左侧,另一部分位于其右侧。

  4. 算法在两部分中分别进行二分查找的原因是什么?
    因为在旋转数组中,目标值可能位于任何一部分。

  5. 如果旋转数组中存在重复元素,算法会发生什么变化?
    算法仍然适用,但需要使用其他方法(如线性搜索)来处理重复元素。