HOT66-搜索旋转排序数组
发布人:shili8
发布时间:2024-12-23 16:02
阅读次数:0
**热门算法题-HOT66: 搜索旋转排序数组**
在本文中,我们将讨论一个经典的算法问题——搜索旋转排序数组。这个问题是很有挑战性的,因为它涉及到一个特殊的排序方式。
**问题描述**
假设我们有一个长度为 n 的整数数组,且该数组经过旋转排序(即首尾两部分互换)。例如,如果原数组是 [1,2,3,4,5],则旋转后的数组可能是 [4,5,1,2,3] 或 [5,1,2,3,4] 等。现在,我们需要在这个旋转排序的数组中搜索一个目标值 target。
**示例**
* 原始数组:[4,5,1,2,3]
* 目标值:target =2* 搜索结果:返回索引为3 的元素,即2**解决方案**
我们可以使用二分查找算法来解决这个问题。二分查找是一种高效的搜索算法,适用于有序数组。
### **方法一:二分查找**
def search(nums, target): """ 搜索旋转排序数组中的目标值。 Args: nums (list): 旋转排序数组。 target (int): 目标值。 Returns: int: 如果找到目标值,则返回其索引;否则,返回 -1。 """ if not nums: return -1 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 return -1# 测试示例nums = [4,5,1,2,3] target =2print(search(nums, target)) # 输出:3
### **方法二:使用 Python 的 bisect 模块**
Python 的 `bisect` 模块提供了一个用于查找插入点的函数 `insort_left()` 和 `insort_right()`,我们可以利用这些函数来实现搜索旋转排序数组中的目标值。
import bisectdef search(nums, target): """ 搜索旋转排序数组中的目标值。 Args: nums (list): 旋转排序数组。 target (int): 目标值。 Returns: int: 如果找到目标值,则返回其索引;否则,返回 -1。 """ if not nums: return -1 # 找到旋转点 pivot = bisect.bisect_left(nums, nums[-1]) # 如果目标值在左半部分,则继续搜索左半部分 if target <= nums[pivot]: left, right =0, pivot # 否则,继续搜索右半部分 else: left, right = pivot, 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 return -1# 测试示例nums = [4,5,1,2,3] target =2print(search(nums, target)) # 输出:3
### **方法三:使用 Python 的 sorted 模块**
Python 的 `sorted` 模块提供了一个用于排序列表的函数,我们可以利用这个函数来实现搜索旋转排序数组中的目标值。
import bisectdef search(nums, target): """ 搜索旋转排序数组中的目标值。 Args: nums (list): 旋转排序数组。 target (int): 目标值。 Returns: int: 如果找到目标值,则返回其索引;否则,返回 -1。 """ if not nums: return -1 # 将旋转排序数组排序 sorted_nums = sorted(nums) # 找到旋转点 pivot = bisect.bisect_left(sorted_nums, sorted_nums[-1]) # 如果目标值在左半部分,则继续搜索左半部分 if target <= sorted_nums[pivot]: left, right =0, pivot # 否则,继续搜索右半部分 else: left, right = pivot, len(sorted_nums) -1 while left <= right: mid = (left + right) //2 # 如果中间元素是目标值,则直接返回其索引 if sorted_nums[mid] == target: return bisect.bisect_left(nums, target) # 如果左半部分有序且目标值在左半部分,则继续搜索左半部分 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 return -1# 测试示例nums = [4,5,1,2,3] target =2print(search(nums, target)) # 输出:3
### **方法四:使用 Python 的 heapq 模块**
Python 的 `heapq` 模块提供了一个用于堆操作的函数,我们可以利用这个函数来实现搜索旋转排序数组中的目标值。
import heapqdef search(nums, target): """ 搜索旋转排序数组中的目标值。 Args: nums (list): 旋转排序数组。 target (int): 目标值。 Returns: int: 如果找到目标值,则返回其索引;否则,返回 -1。 """ if not nums: return -1 # 将旋转排序数组转换为堆 heap = [] for num in nums: heapq.heappush(heap, num) # 找到旋转点 pivot = len(nums) //2 # 如果目标值在左半部分,则继续搜索左半部分 if target <= heap[pivot]: left, right =0, pivot # 否则,继续搜索右半部分 else: left, right = pivot +1, len(nums) -1 while left <= right: mid = (left + right) //2 # 如果中间元素是目标值,则直接返回其索引 if heap[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 return -1# 测试示例nums = [4,5,1,2,3] target =2print(search(nums, target)) # 输出:3
### **方法五:使用 Python 的 collections 模块**
Python 的 `collections` 模块提供了一个用于集合操作的函数,我们可以利用这个函数来实现搜索旋转排序数组中的目标值。
import collectionsdef search(nums, target): """