【二分查找】力扣81:搜索旋转排序数组 II
已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转 ,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,4,4,5,6,6,7] 在下标 5 处经旋转后可能变为 [4,5,6,6,7,0,1,2,4,4] 。
给你 旋转后 的数组 nums 和一个整数 target ,请你编写一个函数来判断给定的目标值是否存在于数组中。如果 nums 中存在这个目标值 target ,则返回 true ,否则返回 false 。
你必须尽可能减少整个操作步骤。
进阶:这是 搜索旋转排序数组 的延伸题目,本题中的 nums 可能包含重复元素。这会影响到程序的时间复杂度吗?会有怎样的影响,为什么?
示例:
输入:nums = [2,5,6,0,0,1,2], target = 0
输出:true
将数组一分为二,其中一定有一个是有序的,另一个可能是有序,也能是部分有序。此时有序部分用二分法查找。无序部分再一分为二,其中一个一定有序,另一个可能有序,可能无序。就这样循环。
即使数组被旋转过,我们仍然可以利用这个数组的递增性,使用二分查找。对于当前的中点,如果它指向的值小于等于右端,那么说明右区间是排好序的;反之,那么说明左区间是排好序的。如果目标值位于排好序的区间内,我们可以对这个区间继续二分查找;反之,我们对于另一半区间继续二分查找。
注意:因为数组存在重复数字,如果中点和左端的数字相同,我们并不能确定是左区间全部相同,还是右区间完全相同,就不知道该在哪个区间继续搜索。在这种情况下,我们可以简单地将左端点右移一位,然后继续进行二分查找。
class Solution:
def search(self, nums: List[int], target: int) -> bool:
if not nums:
return False
n = len(nums)
if n == 1:
return nums[0] == target
low, high = 0, n - 1
while low <= high:
mid = (low + high) // 2
if nums[mid] == target: # 只有此时才True
return True
# 如果中点和左端的数字相同,将左端点右移一位,然后继续进行二分查找
elif nums[mid] == nums[low]:
low += 1
# 右区间是升序
elif nums[mid] <= nums[high]:
if nums[mid] < target and nums[high] >= target: # 如果在右区间范围内就在右区间继续二分查找
low = mid + 1
else: # 如果不在就去左区间继续找
high = mid - 1
# 左区间是升序
else:
if nums[mid] > target and nums[low] <= target:
high = mid - 1
else:
low = mid + 1
return False
时间复杂度:O(n),其中 n 是数组 nums 的长度。最坏情况下数组元素均相等且不为 target,我们需要访问所有位置才能得出结果。
空间复杂度:O(1)。
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/solution/sou-suo-xuan-zhuan-pai-xu-shu-zu-ii-by-l-0nmp/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
力扣81基于力扣33 [搜索旋转排序数组]。
整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
示例:
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
法1:
除了因为没有重复元素,不用考虑mid和left指针上的数是否相同;其实只需要把 return True
改为return mid
返回target的下标,False
改为-1
,即可。
class Solution(object):
def search(self, nums, target):
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[mid] <= nums[right]:
if target > nums[mid] and target <= nums[right]:
left = mid + 1
else:
right = mid - 1
else:
if target < nums[mid] and target >= nums[left]:
right = mid - 1
else:
left = mid + 1
return -1
作者:fuxuemingzhu
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/solution/fu-xue-ming-zhu-bang-zhu-ni-geng-shen-ke-zcu0/
法2比较有意思:
对于旋转数组 nums = [4,5,6,7,0,1,2]
首先根据 nums[0] 与 target 的关系判断 target 是在左段还是右段。
例如 target = 5, 目标值在左半段,因此在 [4, 5, 6, 7, inf, inf, inf] 这个有序数组里找就行了;
例如 target = 1, 目标值在右半段,因此在 [-inf, -inf, -inf, -inf, 0, 1, 2] 这个有序数组里找就行了。
如此,我们又双叒叕将「旋转数组中找目标值」 转化成了「有序数组中找目标值」
Java 代码
class Solution {
public int search(int[] nums, int target) {
int lo = 0, hi = nums.length - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (nums[mid] == target) {
return mid;
}
// 先根据 nums[0] 与 target 的关系判断目标值是在左半段还是右半段
if (target >= nums[0]) {
// 目标值在左半段时,若 mid 在右半段,则将 mid 索引的值改成 inf
if (nums[mid] < nums[0]) {
nums[mid] = Integer.MAX_VALUE;
}
} else {
// 目标值在右半段时,若 mid 在左半段,则将 mid 索引的值改成 -inf
if (nums[mid] >= nums[0]) {
nums[mid] = Integer.MIN_VALUE;
}
}
if (nums[mid] < target) {
lo = mid + 1;
} else {
hi = mid - 1;
}
}
return -1;
}
}
作者:sweetiee
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/duo-si-lu-wan-quan-gong-lue-bi-xu-miao-dong-by-swe/
法3:(暴力解法)一行代码
参透本质,可以看出如果target不在nums里肯定返回的是-1。在的话返回的就是它的下标(而且nums里的值是互不相同的)。Python说:返回下标我熟呀,所以有nums.index(target)。结束。
作者:NfEOaSTGYy
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/by-nfeoastgyy-kagi/
class Solution:
def search(self, nums: List[int], target: int) -> int:
return nums.index(target) if target in nums else -1
作者:zhsama
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/pythonyi-xing-jie-jue-by-zhsama-c98f/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探