题目描述:
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.
分析:
题意:给定一个旋转有序有重复数组,一个目标值,查找该值。如果找到,返回true,否则返回false。
思路:这道题是LeetCode 33的进化版本,仍然采用二分法。假设数组nums的大小为n,目标值为target,那么两者区别在于:Ⅰ. LeetCode 30给定的是旋转有序非重复数组,已经证明,对于经过旋转的数组,任意选择一个j作为分割点,nums[0→j - 1]、nums[j→n - 1]至少有一段是升序的;Ⅱ. 本题给定的是旋转有序有重复数组,则不满足这个性质,给出反例:数组 1, 3, 1, 1, 1 中查找目标值3,此时经过第一次分隔,不存在升序子数组。
由上例可知,本题中,某些情形需要对两个子数组同时搜索,因此我们采用DFS搜索和二分法结合的方式,初始化指针left = 0,right = n - 1,则mid = left + ((right - left) >> 1)。① 如果target等于nums[left]、nums[mid]或者nums[right],那么已经找到target,返回true;② 如果target处于nums[left]和nums[mid]之间,那么继续进入左子数组[left→mid - 1]搜索;③ 如果target处于nums[mid]和nums[right]之间,那么继续进入右子数组[mid + 1→right]搜索;④ 其它情况,需要同时进入两个子数组[left→mid - 1]和[mid + 1→right]搜索。
代码:
#include <bits/stdc++.h>
using namespace std;
class Solution {
private:
bool ans;
void DFS(vector<int>& nums, int left, int right, int& target){
if(ans || (left > right)){
return;
}
if(left == right){
if(nums[left] == target){
ans = true;
}
return;
}
int mid = left + ((right - left) >> 1);
if(nums[left] == target || nums[mid] == target || nums[right] == target) {
ans = true;
return;
}
if(nums[left] <= target && target <= nums[mid]){
DFS(nums, left, mid - 1, target);
}
else if(nums[mid] <= target && target <= nums[right]){
DFS(nums, mid + 1, right, target);
}
else{
DFS(nums, left, mid - 1, target);
DFS(nums, mid + 1, right, target);
}
}
public:
bool search(vector<int>& nums, int target) {
int n = nums.size();
if(!n){
return false;
}
ans = false;
DFS(nums, 0, n - 1, target);
return ans;
}
};