数据结构与算法之 leetcode 二分查找旋转数组极值改进 处理重复

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


二分查找旋转数组极值改进(处理重复)——LeetCode算法挑战

在LeetCode等编程竞赛平台中,算法题是考察程序员逻辑思维和编程能力的重要环节。其中,二分查找是算法中的经典问题,而旋转数组则是二分查找的一个变种。本文将围绕“二分查找旋转数组极值改进(处理重复)”这一主题,深入探讨如何解决这一问题。

问题背景

旋转数组是指将一个数组中的元素按照某个位置进行旋转,使得数组的前半部分和后半部分颠倒。例如,数组[0,1,2,4,5,6,7]经过一次旋转后可能变为[4,5,6,7,0,1,2]。在旋转数组中,寻找最大值或最小值是一个常见的问题。

在传统的二分查找中,我们通常假设数组是有序的。在旋转数组中,数组被旋转后,有序性被破坏,因此我们需要对二分查找算法进行改进。

改进二分查找算法

为了解决旋转数组中寻找极值的问题,我们可以对传统的二分查找算法进行改进。以下是改进后的算法步骤:

1. 初始化两个指针`left`和`right`,分别指向数组的第一个和最后一个元素。

2. 当`left`小于等于`right`时,执行以下步骤:

a. 计算中间位置`mid`。

b. 如果`nums[mid]`等于`nums[left]`,则无法确定最小值或最大值的位置,因此将`left`和`mid`都向右移动一位。

c. 如果`nums[mid]`大于等于`nums[left]`,则最小值在`left`到`mid`之间,将`right`更新为`mid - 1`。

d. 如果`nums[mid]`小于等于`nums[left]`,则最大值在`mid`到`right`之间,将`left`更新为`mid + 1`。

3. 当`left`大于`right`时,循环结束,此时`left`指向的元素即为最小值,`right`指向的元素即为最大值。

代码实现

以下是改进后的二分查找算法的Python代码实现:

python

def findMin(nums):


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


while left < right:


mid = (left + right) // 2


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


left += 1


mid += 1


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


right = mid - 1


else:


left = mid + 1


return nums[left]

def findMax(nums):


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


while left < right:


mid = (left + right) // 2


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


right -= 1


elif nums[mid] >= nums[right]:


left = mid + 1


else:


right = mid - 1


return nums[right]


测试用例

以下是一些测试用例,用于验证改进后的二分查找算法的正确性:

python

nums1 = [4, 5, 6, 7, 0, 1, 2]


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


nums3 = [7, 0, 1, 2, 3, 4, 5]


nums4 = [1, 1, 1, 0, 1, 1, 1]

print(findMin(nums1)) 输出:0


print(findMax(nums1)) 输出:7


print(findMin(nums2)) 输出:1


print(findMax(nums2)) 输出:7


print(findMin(nums3)) 输出:0


print(findMax(nums3)) 输出:7


print(findMin(nums4)) 输出:0


print(findMax(nums4)) 输出:1


总结

本文针对LeetCode中的“二分查找旋转数组极值改进(处理重复)”问题,介绍了改进后的二分查找算法。通过分析旋转数组的特性,我们成功解决了在旋转数组中寻找极值的问题。在实际应用中,这种改进的二分查找算法可以有效地提高算法的效率。