整数数组 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) 的算法解决此问题
class Solution {
public:
int search(vector<int>& nums, int target) {
if (nums.empty())
return -1;
int l = 0, r = nums.size() - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (nums[mid] >= nums[0])
l = mid;
else
r = mid - 1;
}
if (target >= nums[0])
l = 0;
else
l++, r = nums.size() - 1;
while (l < r) {
int mid = l + r >> 1;
if (nums[mid] >= target)
r = mid;
else
l = mid + 1;
}
return nums[r] == target ? r : -1;
}
};
应用二分查找的思路
首先获得容器数组的长度并且设置好l和r
第一个while循环的目的是反复比较从而找出变换前的最大元素位置(其实就是最后一个元素,因为数组默认升序)
接下来通过if else语句判断target元素比首元大还是小,如果更大的话说明在翻转后的前半段里,将l设置为0;反之则取后半段,将l设置为l++(即变换前首个元素位置,或者说最小的元素),同时将r的位置重新设置为数组尾部。
处理完上述过程,开始应用二分查找,通过比较mid位置元素与target元素的大小不断二分缩小查找空间。当mid位置元素大小大于等于target时说明target元素在mid左侧或刚好在该位置,故将r设置为mid,下次从左侧空间查找;反之,mid位置元素大小大于target时说明target元素在mid右侧,故将l设置为mid+1,下次从右侧空间查找。
最终若找到则返回该位置下标。