题目描述
给你一个整数数组 nums ,和一个整数 target 。
该整数数组原本是按升序排列,但输入时在预先未知的某个点上进行了旋转。(例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
请你在数组中搜索 target ,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
示例 1:
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
示例 2:
输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1
示例 3:
输入:nums = [1], target = 0
输出:-1
提示:
1 <= nums.length <= 5000
-10^4 <= nums[i] <= 10^4
nums 中的每个值都 独一无二
nums 肯定会在某个点上旋转
-10^4 <= target <= 10^4
解题思路
首先就是暴力求解法:顺序遍历数组,比较每个元素,时间复杂度为O(N)。
如果要在时间复杂度为O(logN)的条件下解决该题,则需要用到二分法查找,首先给出二分法代码模板:
int binarySearch(const 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;
else if(nums[mid] < target) left = ++mid;
else right = --mid;
}
return -1;
}
解题步骤:
一般情况下,二分法存在left,right,mid位,来辅助判断。因此,二分法解决该题的步骤如下:
- 如果target 在[mid+1,right]序列中,则left = mid+1,否则 right = mid;
- 关键是如何判断 target在[mid+1,right]序列中,具体判断如下:
当[0, mid] 序列是升序: nums[0] <= nums[mid], 当target > nums[mid] || target < nums[0] ,则向后规约;
当[0, mid] 序列存在旋转位: nums[0] > nums[mid],当target < nums[0] && target > nums[mid],则向后规约;
当然其它情况就是向前规约了; - 循环判断,直到排除到只剩最后一个元素时,退出循环,如果该元素和 target 相同,直接返回下标,否则返回 -1。
根据解题思路套用二分法模板,具体代码实现如下:
class Solution {
public:
int search(vector<int>& nums, int target) {
int L=0,R=nums.size()-1;
while(L<R) {
int mid = L + (R-L)/2;
if( nums[0] <= nums[mid] && ( target > nums[mid] || target < nums[0]))
L = ++mid;
else if( target > nums[mid] && target < nums[0])
L = ++mid;
else
R = mid;
}
return L==R && nums[L]==target ? L : -1;
}
};
AC结果:
![f94b8c66216103600a522d6b72b6aece.png](https://i-blog.csdnimg.cn/blog_migrate/7ce6184a2cb6afd2b34fe7c4e599346f.jpeg)
利用异或对判断条件语句进行简化,简化后的写法如下:
class Solution {
public:
int search(vector<int>& nums, int target) {
int L=0,R=nums.size()-1;
while(L<R) {
int mid = L + (R-L)/2;
if((nums[0] > target) ^ (nums[0] > nums[mid]) ^ (target > nums[mid]))
L = ++mid;
else
R = mid;
}
return L==R && nums[L]==target ? L : -1;
}
};
AC结果:
![053021ec72724f5ff1c54855b57bd348.png](https://i-blog.csdnimg.cn/blog_migrate/41dfdcb42d86aed51cfc92504c0c8ddd.jpeg)
复杂度分析:
- 时间复杂度:二分查找,时间复杂度为O(logN);
- 空间复杂度:空间复杂度为O(1)。