数据结构与算法之 leetcode 二分查找旋转数组搜索算法 处理重复

数据结构与算法阿木 发布于 2025-07-12 11 次阅读


二分查找在旋转数组搜索算法中的应用与优化(处理重复元素)

二分查找是一种在有序数组中查找特定元素的非常高效的方法。当数组被旋转时,即数组的一部分被移动到了数组的另一部分之前,传统的二分查找方法就不再适用。本文将探讨如何在旋转数组中实现二分查找,并针对重复元素的情况进行优化。

旋转数组概述

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

传统二分查找的局限性

在旋转数组中,传统的二分查找方法会遇到以下问题:

1. 无法确定旋转点的位置。

2. 无法确定目标值位于旋转部分的哪一侧。

旋转数组二分查找算法

为了解决上述问题,我们需要对二分查找算法进行修改。以下是旋转数组二分查找算法的基本步骤:

1. 确定旋转点的位置。

2. 根据旋转点的位置,将数组分为两部分:左半部分和右半部分。

3. 判断目标值位于哪一侧,并递归地在该侧进行二分查找。

以下是旋转数组二分查找算法的Python实现:

python

def search(nums, target):


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



while left <= right:


mid = (left + right) // 2



如果找到目标值,返回索引


if nums[mid] == target:


return mid



如果左半部分有序


if nums[left] <= nums[mid]:


如果目标值在左半部分


if nums[left] <= target < nums[mid]:


right = mid - 1


else:


left = mid + 1


如果右半部分有序


else:


如果目标值在右半部分


if nums[mid] < target <= nums[right]:


left = mid + 1


else:


right = mid - 1



如果未找到目标值,返回-1


return -1


处理重复元素

在实际应用中,旋转数组中可能存在重复元素,这会使得旋转点的确定变得复杂。以下是对上述算法的改进,以处理重复元素的情况:

1. 当遇到重复元素时,先判断重复元素是否为目标值。

2. 如果不是目标值,则将重复元素的范围缩小,继续进行二分查找。

以下是改进后的算法实现:

python

def search_with_duplicates(nums, target):


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



while left <= right:


mid = (left + right) // 2



如果找到目标值,返回索引


if nums[mid] == target:


return mid



如果左右两端的元素相同,无法确定旋转点,尝试缩小范围


if nums[left] == nums[mid]:


left += 1


right -= 1


如果左半部分有序


elif nums[left] <= nums[mid]:


如果目标值在左半部分


if nums[left] <= target < nums[mid]:


right = mid - 1


else:


left = mid + 1


如果右半部分有序


else:


如果目标值在右半部分


if nums[mid] < target <= nums[right]:


left = mid + 1


else:


right = mid - 1



如果未找到目标值,返回-1


return -1


总结

本文介绍了在旋转数组中实现二分查找的方法,并针对重复元素的情况进行了优化。通过改进后的算法,我们可以在旋转数组中高效地查找目标值,即使存在重复元素也能保持较高的查找效率。

后续思考

1. 如何进一步优化算法,以处理更多特殊情况,如旋转数组中存在多个旋转点?

2. 如何将二分查找算法应用于其他数据结构,如链表和树?

3. 如何将二分查找算法与其他算法结合,以解决更复杂的问题?