本题是二分搜索的变体,在后端开发岗位的面试中出现频率较高。在此将题解分享给大家。
python、C++入门资料领取,目前在本平台:
1、进入本博客主页
2、在 资源 中可以下载它们
今天的题目:
题目描述:
题号:34
整数数组 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
。
你必须设计一个时间复杂度为 O(log n)
的算法解决此问题。
解题思路:
思路一:二分查找 + 判断是否有序
1、初始化两个指针,left指向数组的起始位置,right指向数组的末尾位置。
2、进入循环,当left小于等于right时执行以下步骤:
计算中间位置mid,mid = left + (right - left) / 2,防止整数溢出。
如果nums[mid]等于target,则找到目标值,返回mid。
判断哪一部分是有序的,并根据有序部分确定下一步的查找范围:
(1)如果nums[left]到nums[mid]是有序的:
-
如果target在nums[left]到nums[mid]之间,则将right更新为mid - 1,继续在左半部分查找。
-
否则,将left更新为mid + 1,继续在右半部分查找。
(2)如果nums[mid]到nums[right]是有序的:
-
如果target在nums[mid]到nums[right]之间,则将left更新为mid + 1,继续在右半部分查找。
-
否则,将right更新为mid - 1,继续在左半部分查找。
3、如果循环结束仍未找到目标值,则返回-1,表示目标值不存在于数组中。
时间复杂度:O(log n)
空间复杂度:O(1)
C++
// C++
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
}
if (nums[left] <= nums[mid]) {
if (nums[left] <= target && target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
} else {
if (nums[mid] < target && target <= nums[right]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}
};
go
// go
func search(nums []int, target int) int {
left, right := 0, len(nums)-1
for left <= right {
mid := left + (right - left) / 2
if nums[mid] == target {
return mid
}
if nums[left] <= nums[mid] {
if nums[left] <= target && target < nums[mid] {
right = mid - 1
} else {
left = mid + 1
}
} else {
if nums[mid] < target && target <= nums[right] {
left = mid + 1
} else {
right = mid - 1
}
}
}
return -1
}