返回

算法新体验:探秘LeetCode第81题“搜索旋转排序数组 II”

后端

征服 LeetCode 81:搜索旋转排序数组 II,算法入门指南

作为一名算法初学者,你肯定听说过 LeetCode,一个必不可少的在线学习平台,帮助你提升算法技能。其中,第 81 题——“搜索旋转排序数组 II”就是一道经典的算法难题,让我们共同踏上解题之旅吧!

问题

给你一个可能有重复元素的整数数组 nums 和一个整数 target。你的任务是找到 targetnums 中的下标,如果存在返回下标,否则返回 -1

解题思路

这道题的解题关键在于二分搜索和处理旋转数组的技巧。

步骤 1:确定旋转点

首先,我们需要找出旋转点,即数组中第一个比最后一个元素小的元素。我们可以通过二分搜索来确定这个旋转点。

步骤 2:判断 target 在哪个子数组中

确定了旋转点后,我们需要判断 target 位于数组的哪一侧。如果 target 位于旋转点右侧,那么它肯定在排序的一侧;如果 target 位于旋转点左侧,那么它可能在排序的一侧或另一侧。

步骤 3:二分搜索查找 target

在确定 target 所在的子数组后,我们就可以进行二分搜索来查找 target 的下标。

代码示例

def search(nums, target):
  # 确定旋转点
  left, right = 0, len(nums) - 1
  while left < right:
    mid = left + (right - left) // 2
    if nums[mid] > nums[right]:
      left = mid + 1
    else:
      right = mid

  # 判断 target 在哪个子数组中
  if nums[left] == target:
    return left
  elif nums[right] == target:
    return right
  else:
    return -1

# 在确定的子数组中进行二分搜索
def binary_search(nums, target, left, right):
  while left <= right:
    mid = left + (right - left) // 2
    if nums[mid] == target:
      return mid
    elif nums[mid] < target:
      left = mid + 1
    else:
      right = mid - 1
  return -1

# 主函数
if __name__ == "__main__":
  nums = [4, 5, 6, 7, 0, 1, 2]
  target = 0
  result = search(nums, target)
  print(result)

注意事项

  1. 在判断 target 所在子数组时,需要处理 target 等于 nums[left]nums[right] 的特殊情况。
  2. 在二分搜索查找 target 时,需要处理 left 等于 right 的特殊情况。

总结

通过解决 LeetCode 81 题,“搜索旋转排序数组 II”,我们可以加深对二分搜索算法的理解,并掌握处理旋转数组的技巧。

常见问题解答

1. 如何确定旋转点?

通过二分搜索,找出第一个比最后一个元素小的元素。

2. 为什么需要判断 target 在哪个子数组中?

因为数组被旋转了,我们需要知道 target 位于排序的一侧还是另一侧。

3. 如何处理 target 等于 nums[left] 和 nums[right] 的情况?

在判断 target 所在子数组时,需要特殊处理这种情况。

4. 如何处理 left 等于 right 的情况?

在二分搜索查找 target 时,需要特殊处理这种情况,避免死循环。

5. 为什么这道题是中等难度的?

因为需要同时使用二分搜索和处理旋转数组的技巧,对算法基础有一定的要求。