假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
你可以假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。
输入: nums = [4,5,6,7,0,1,2], target = 0 输出: 4
方法一:递归法
思路:
【1】找到数组的中间位置,与头节点比较,若大于头节点,则前半部分有序,后半部分可能有序,可能无序。
【2】若小于头节点则前半部分可能有序,可能无序。后半部分肯定有序。
【3】若target在有序部分则进行二分查找,在无序部分则递归第一步骤,直到找到有序部分。
//二分查找法
int halfSearch(int begin, int end, vector<int> nums, int target) {
while (begin <= end) {
int mid = (begin + end) / 2;
if (nums[mid] == target)
return mid;
else if (nums[mid] < target) {
begin = mid + 1;
}
else {
end = mid - 1;
}
}
return -1;
}
//递归查找
int dpSearch(int begin, int end, vector<int> nums, int target) {
if (begin <= end) {
int mid = (begin + end) / 2;
int index = -1; //target下标
if (nums[mid] == target)
return mid;
//前半部分有序
if (nums[mid] > nums[begin]) {
//target在前半部分进行二分查找
index = halfSearch(begin, end - 1, nums, target);
if (index != -1)
return index;
//没在前半部分,对后半部分进行递归查找
index = dpSearch(mid + 1, end, nums, target);
return index;
}
else { //后半部分有序
index = halfSearch(mid + 1, end, nums, target);
if (index != -1)
return index;
index = dpSearch(begin, mid - 1, nums, target);
return index;
}
}
return -1;
}
int search(vector<int>& nums, int target) {
return dpSearch(0, nums.size() - 1, nums, target);
}
方法二:递归法(改进)
思路: 在方法一的基础上,在有序部分也使用递归查询。
//递归查找
int dpSearch(int begin, int end, vector<int> nums, int target) {
if (begin <= end) {
int mid = (begin + end) / 2;
int index = -1; //target下标
if (nums[mid] == target)
return mid;
//前半部分有序
if (nums[mid] >= nums[begin]) { //这里的判断条件为>=,而不是>。
if (nums[mid] > target&&target >= nums[begin]) {
return dpSearch(begin, mid - 1, nums, target);
}
else {
return dpSearch(mid + 1, end, nums, target);
}
}
else { //后半部分有序
if (nums[mid] < target&&target <= nums[end]) {
return dpSearch(mid + 1, end, nums, target);
}
else {
return dpSearch(begin, mid - 1, nums, target);
}
}
}
return -1;
}
int search(vector<int>& nums, int target) {
return dpSearch(0, nums.size() - 1, nums, target);
}