LeetCode HOT 100:搜索旋转排序数组
题目:33. 搜索旋转排序数组
题目描述:
一个整数数组,数组每个值都不相同,且该整数数组是一个被旋转过的数组。被旋转过的数组是指,由一个递增的数组,从某一个下标开始往后的元素,移到最开头。举个例子:数组[1, 3, 4, 5, 7]
,假设从下标为2
处开始旋转,得到旋转过的数组为[4, 5, 7, 1, 3]
,如果从下标0
处开始旋转,那么相当于没有旋转,还是原数组。
本题能保证,给你的整数数组,一定是每个值都不相同,且一定是一个旋转过的数组。然后给你一个target
的值,让你返回target
值在数组中的下标,如果target
不在数组中,返回-1
。要求时间复杂度为O(logn)
。
步骤:
这题一看要求时间复杂度O(logn)
,想到使用二分法,但是二分法需要数组满足递增,乍一看本题并不满足。但是还是可以使用二分法,只不过思路稍微转变一下。
1、下标l
为0
,r
为n - 1
,开始进行二分。取得两者中间下标mid
,如果mid
下标的值正好等于target
,直接返回结果即可。
2、如果[l, mid]
是有序数组,且 target
值在[l, mid]
范围上,则我们应该将搜索范围缩小至 [l, mid - 1]
,否则在[mid + 1, r]
范围中寻找。
3、如果[mid, r]
是有序数组,且 target
值在[mid, r]
范围上,则我们应该将搜索范围缩小至 [mid + 1, r]
,否则在[l, mid - 1]
范围中寻找。
解释:
1、为什么本题可以使用二分法?二分法一般都需要数组有序。这个数组因为被旋转过,看似是无序的,其实是局部有序的。例如[4, 5, 7, 1, 3]
,[4, 5, 7]
和[1, 3]
都是有序的,所以在某些有序范围内,可以进行二分。
2、为什么要判断[l, mid]
或[mid, r]
是否有序?因为只有有序了,才能进行范围缩小。而至于在有序范围中怎么缩小,上面的步骤2
和3
说得很清晰了。
代码:
public int search(int[] nums, int target) {
int N = nums.length;
if (N == 0) return -1;
if (N == 1) return nums[0] == target ? 0 : -1;
int L = 0, R = N - 1;
int M = 0;
while (L <= R) {
M = L + ((R - L) >> 1);
if (nums[M] == target) return M;
// [L, M]有序,说明[L, R]无序
if (nums[L] <= nums[M]) {
// target在[L, M]范围上,接下来左侧继续二分
if (target >= nums[L] && target < nums[M]) {
R = M - 1;
} else { // 去右侧二分
L = M + 1;
}
} else { // [L, M]无序,说明[M, R]有序
if (target > nums[M] && target <= nums[R]) { // 如果[M, R]范围上包括了target,去右侧二分
L = M + 1;
} else { // 去左侧二分
R = M - 1;
}
}
}
return -1;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 我与微信审核的“相爱相杀”看个人小程序副业
· DeepSeek “源神”启动!「GitHub 热点速览」
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库