题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
解题思路:
解法一:直接从前往后搜索,时间复杂度O(n)
AC代码:
class Solution {
public boolean search(int[] nums, int target) {
for (int num : nums) {
if (num == target) {
return true;
}
}
return false;
}
}
解法二:二分查找
因为有序数组nums预先是在k位置进行了旋转,那么对于任意一个下标 i ,会将nums分为左半部分和右半部分,那么左半部分和右半部分一定是一个有序,一个无序的。所以如果能够确定哪一部分有序,那么就可以在有序的那一部分使用二分查找。
确定那一部分有序:对于下标 left ,mid,right,将nums分为两部分nums[left,mid],nums[mid,right]
- 如果nums[left] < nums[mid],说明左半部分有序
- 否则,即nums[mid]<nums[right],说明右半部分有序
- 但是有种特殊情况,判断不出哪一部分是否有序,那就是nums[left] == nums[mid]这种情况,比如 [ 1,0,1,1,1 ],当 left =0,mid = 2时,此时nums[left] == nums[mid],此时如果出现这种情况,就令 left++,将最左边重复的那一项去掉,直到不会出现nums[left] != nums[mid],这个时候,就可以判断出那一部分有序,之后就一直在有序的那一部分进行二分查找
AC代码:
class Solution {
public boolean search(int[] nums, int target) {
int left = 0;
int right = nums.length;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return true;
}
//此时判断不出那一部分有序,令left++,去除重复项
if (nums[left] == nums[mid]) {
left++;
continue;
}
if (nums[left] < nums[mid]) {//左半部分有序
//target在左部分中
if (nums[left] <= target && nums[mid] > target) {
right = mid;
}else {
//在右半部分中
left=mid+1;
}
}else {//右半部分有序
//在右半部分中
if (nums[mid]<target&&nums[right-1]>=target){
left = mid+1;
}else {
//在作伴部分中
right =mid;
}
}
}
return false;
}
}
不过这种解法在最坏情况下的时间复杂度和方法一相同,都为O(n)