数据结构与算法之 leetcode 二分查找旋转数组算法 二分法变种

数据结构与算法阿木 发布于 3 天前 2 次阅读


二分查找在旋转数组中的应用:算法解析与实现

二分查找是一种在有序数组中查找特定元素的非常高效的方法。当数组被旋转时,即数组的一部分被移动到了数组的另一部分之前,传统的二分查找方法就不再适用。本文将探讨如何使用二分查找的变种来解决旋转数组中的查找问题。

旋转数组概述

旋转数组是指一个数组被旋转了若干次,每次旋转都是将数组中的元素整体向右移动若干位。例如,一个原始数组 `[1, 2, 3, 4, 5, 6, 7]` 经过一次旋转后可能变为 `[6, 7, 1, 2, 3, 4, 5]`。

二分查找变种:旋转数组中的查找

在旋转数组中查找特定元素,我们可以通过以下步骤实现:

1. 确定旋转数组的旋转点。

2. 根据旋转点将问题分为两个子问题:在左半部分查找或在右半部分查找。

3. 应用二分查找算法在选定的子数组中查找目标值。

确定旋转点

我们需要找到旋转点。旋转点是指数组中第一个大于前一个元素的索引。以下是一个确定旋转点的函数实现:

python

def find_rotation_point(nums):


left, right = 0, len(nums) - 1


while left < right:


mid = (left + right) // 2


if nums[mid] > nums[mid + 1]:


return mid + 1


elif nums[mid] < nums[left]:


right = mid


else:


left = mid + 1


return 0


二分查找变种

接下来,我们实现一个在旋转数组中查找特定元素的函数:

python

def search_in_rotated_array(nums, target):


rotation_point = find_rotation_point(nums)


left, right = 0, len(nums) - 1

while left <= right:


mid = (left + right) // 2


real_mid = (mid + rotation_point) % len(nums)

if nums[real_mid] == target:


return real_mid


elif nums[real_mid] < target:


left = mid + 1


else:


right = mid - 1

return -1


完整代码示例

以下是完整的代码示例,包括旋转数组的生成和查找函数:

python

def find_rotation_point(nums):


left, right = 0, len(nums) - 1


while left < right:


mid = (left + right) // 2


if nums[mid] > nums[mid + 1]:


return mid + 1


elif nums[mid] < nums[left]:


right = mid


else:


left = mid + 1


return 0

def search_in_rotated_array(nums, target):


rotation_point = find_rotation_point(nums)


left, right = 0, len(nums) - 1

while left <= right:


mid = (left + right) // 2


real_mid = (mid + rotation_point) % len(nums)

if nums[real_mid] == target:


return real_mid


elif nums[real_mid] < target:


left = mid + 1


else:


right = mid - 1

return -1

示例


nums = [6, 7, 1, 2, 3, 4, 5]


target = 3


print(search_in_rotated_array(nums, target)) 输出:4


性能分析

旋转数组中的二分查找变种的时间复杂度为 O(log n),空间复杂度为 O(1),与传统的二分查找相同。这是因为我们仍然在每次迭代中减少搜索范围的一半。

总结

本文介绍了如何在旋转数组中使用二分查找变种来查找特定元素。通过确定旋转点并应用二分查找,我们可以在 O(log n) 的时间复杂度内找到目标值。这种方法在处理旋转数组时非常有效,尤其是在大数据集上。