Problem
Search in Rotated Sorted Array
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
具体详见Leetcode
Search in Rotated Sorted ArrayII
Follow up for “Search in Rotated Sorted Array”:
What if duplicates are allowed?Would this affect the run-time complexity? How and why?
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).
Write a function to determine if a given target is in the array.
The array may contain duplicates.
具体详见Leetcode
Analysis
Search in Rotated Sorted Array
首先这是一道有序的题目,但是和有序又有点不一样,因为有一部分是前后翻转的,所以是分段有序。因为保持了部分有序的特性,所以可以采用二分查找的方法。但是每一次查找的时候有一下几种情况:
(1)每一次对当前的数组从start下标开始到end下标处理。
(2)判断start和end中间的中位数mid对应的元素是否是要找的target,如果是直接修改要找的target的index。完成查找。否则继续查找。
(3)首先判断从下标mid对应的数组元素和下标end对应元素的大小。
(4)如果nums[mid]小于nums[end],说明后半段是正常的,并没有翻转隔断,同时说明前半段不正常。在这种情况下,判断mid对应的元素和target的大小,如果target同时大于mid和end对应的元素,说明大的部分在前面,则继续对下标范围为start到mid-1这部分的元素做二分查找,否则则继续对下标范围为mid+1到end这部分的元素做二分查找,如果target小于mid对应的元素则就对下标范围为start到mid-1的这部分元素做二分查找。
(5)如果nums[mid]大于nums[end],说明后半段是不正常的,并有翻转隔断,同时说明前半段正常。在这种情况下,判断mid对应的元素和target的大小,如果target小于start对应的元素,则继续对下标范围为mid+1到end这部分的元素做二分查找,否则就比较target和mid对应元素的大小,如果target较大,说明要对下标范围为mid+1到end这部分的元素做二分查找,否则对下标范围为start到mid-1的这部分元素做二分查找。
Search in Rotated Sorted ArrayII
与(1)最主要的不同在于当mid对应的元素和end对应的元素相等时,没有办法判断哪边不正常,所以需要对两边都进行二分查找。
Complexity
Search in Rotated Sorted Array
时间复杂度:
O(log2n)
空间复杂度:
O(1)
Search in Rotated Sorted ArrayII
时间复杂度:最好情况是
O(log2n)
,最坏情况是
O(n)
空间复杂度:
O(1)
Code
Search in Rotated Sorted Array
class Solution {
public:
void bisearch(vector<int>& nums, int start, int end, int target) {
int mid = (start + end) / 2;
if (start > end) return;
if (nums[mid] == target) {
index = mid;
return;
}
//normal
if (nums[mid] < nums[end]) {
if (target > nums[mid]) {
if (target > nums[end]) {
bisearch(nums,start, mid-1,target);
} else {
bisearch(nums,mid+1, end, target);
}
} else {
bisearch(nums, start, mid-1, target);
}
} else {
//mess like 4 5 6 7 0 1 2
if (target < nums[start]) {
bisearch(nums,mid+1,end,target);
} else {
if (target > nums[mid]) {
bisearch(nums, mid+1, end,target);
} else {
bisearch(nums,start,mid-1,target);
}
}
}
}
int search(vector<int>& nums, int target) {
index = -1;
bisearch(nums,0,nums.size()-1,target);
return index;
}
private:
int index;
};
Search in Rotated Sorted ArrayII
class Solution {
public:
void bisearch(vector<int>& nums, int start, int end, int target) {
int mid = (start + end) / 2;
if (start > end) return;
if (nums[mid] == target) {
index = mid;
return;
}
//normal
if (nums[mid] < nums[end]) {
if (target > nums[mid]) {
if (target > nums[end]) {
bisearch(nums,start, mid-1,target);
} else {
if (nums[end] == target) index = end;
else bisearch(nums,mid+1, end, target);
}
} else {
bisearch(nums, start, mid-1, target);
}
} else if (nums[mid] > nums[end]) {
//mess like 4 5 6 7 0 1 2
if (target < nums[start]) {
bisearch(nums,mid+1,end,target);
} else {
if (target == nums[start]) {
index = start;
} else {
if (target > nums[mid]) {
bisearch(nums, mid+1, end,target);
} else {
bisearch(nums,start,mid-1,target);
}
}
}
} else {
bisearch(nums,start, mid-1,target);
bisearch(nums,mid+1, end, target);
}
}
bool search(vector<int>& nums, int target) {
index = -1;
bisearch(nums,0,nums.size()-1,target);
return (index!=-1);
}
private:
int index;
};