题目如下:
Follow up for "Search in Rotated Sorted Array":
What if duplicates are allowed?
Would this affect the run-time complexity? How and why?
Write a function to determine if a given target is in the array.
分析如下:
在有重复元素的情况下,如果使用上一题的代码,就会出错。比如在这样的例子中,在{1,3,1,1,1}中找3,上一题代码中的else if(A[mid]>=A[l])就会判断失效。
解决这个问题可以这样。分情况处理。第一种情况,如果出现了重复,也就是说如果A[mid]==A[i],那么就既不丢弃mid左半部分,也不丢弃mid右半部分,老老实实地只丢弃一个元素。第二种情况,如果没有出现重复,就进行和上一题一样的处理。
我的代码:
//72ms过大集合
class Solution {
public:
bool search(int A[], int n, int target) {
int l=0;
int r=n-1;
while(l<=r){
int mid=l+(r-l)/2;
if(A[mid]==target){
return true;
}else if(A[mid]==A[l]){
l++; //出现重复,所以没法丢弃一半的元素,只能丢弃1个元素。
}else if(A[mid]>A[l]){
if(target<A[mid]&&target>=A[l])
r=mid-1;
else
l=mid+1;
}else {
if(target<=A[r]&&target>A[mid])
l=mid+1;
else
r=mid-1;
}
}
return false;
}
};
// 48ms过大集合
class Solution {
public:
bool search(int A[], int n, int target) {
int l=0;
int r=n-1;
while(l<=r){
int mid=l+(r-l)/2;
if(A[mid]==target){
return true;
}else if(A[mid]==A[l]){
int mid_mid=l+(mid-l)/2;//找到mid和l的中点mid_mid,
if(A[mid_mid]==target)
return true;
if(A[mid_mid]>A[l])//判断从l到mid_mid是否单调递增。如果是,pivot必然不在这个区间,这个区间单调递增,转化为最常规的情况了。
if(target<A[mid_mid]&&target>=A[l])
r=mid-1;
else
l=mid+1;
else//否则,从l到mid_mid就不是单调递增,说明pivot可能出现在这个区间,没法确定它在哪里,所以每次只能丢弃1个元素。
l++;
}else if(A[mid]>A[l]){
if(target<A[mid]&&target>=A[l])
r=mid-1;
else
l=mid+1;
}else {
if(target<=A[r]&&target>A[mid])
l=mid+1;
else
r=mid-1;
}
}
return false;
}
};
update : 2015-01-20
其实这道题目这么理解就比较容易了。
如果没有重复元素,就用Search in Rotated Sorted Array 这道题目的思路,进行一个类似分查找的查找,每次丢弃当前数组的一半。如果有重复元素,每次只能丢弃一个。
迭代版本
// 迭代版本 12ms
class Solution {
public:
bool search(int A[], int n, int target) {
int start = 0, end = n - 1, mid = 0;
while (start <= end) {
mid = start + (end -start) / 2;
if (A[mid] == target) {
return true;
} else if (A[mid]== A[start]) {
start = start + 1;
} else if (A[mid] == A[end]) {
end = end -1;
} else if (A[mid] > A[end]) {
if (target < A[mid] && target >= A[start])
end = mid - 1;
else
start = mid + 1;
} else {
if (target > A[mid] && target <= A[end])
start = mid + 1;
else
end = mid - 1;
}
}
return false;
}
};
递归版本
//递归版本 10ms
class Solution {
public:
bool search(int A[], int start, int end, int target) {
if ( start > end ) return false;
int mid = start + (end - start) / 2 ;
if (target == A[mid]) {
return true;
}else if (A[mid] == A[end]) {
return search(A, start, end - 1, target);
}else if (A[mid] == A[start]) {
return search(A, start + 1, end, target);
} else if (A[mid] > A[end]) {
if (target < A[mid] && target >= A[start])
return search (A, start, mid - 1, target);
else
return search (A, mid + 1, end, target);
}else {
if (target > A[mid] && target <= A[end])
return search (A, mid + 1, end, target);
else
return search(A, start, mid - 1, target);
}
}
bool search(int A[], int n, int target) {
return search (A, 0, n - 1, target);
}
};