- 题目描述
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.
Your algorithm’s runtime complexity must be in the order of O(log n). - 解决方案
可能解决本题目的方案有多种,这里作者提供两种解法。
1)最常规的思路是采用折半查找法,但是由于原来的有序数组按照某个轴进行了宣战,所以,在判断条件上会有一些麻烦。如果数组没有按照某个轴旋转,则就是普通的这般查找;如果数组按照某个轴完成了旋转,则有nums[left] >= nums[right],这是需要判nums[middle]、target、(nums[right]或nums[left]之间选择一个)这三者之间的大小关系,来更新left或right。
- 第二种方法是找到旋转轴,然后根据旋转轴将旋转后的数组与原来的数组完成位置映射,从而利用传统的折半查找法即可解决。
- 代码
1)解决方案1代码
#include <iostream>
#include <vector>
using namespace std;
int search(vector<int>& nums, int target);
int main()
{
vector<int> vec;
int a[] = {4,5,6,7,0,1,2};
for (int i=0; i<sizeof(a)/sizeof(a[0]); i++){
vec.push_back(a[i]);
}
int result = search(vec, 7);
cout << result << endl;
return 0;
}
int search(vector<int>& nums, int target){
if (nums.empty()){
return -1;
}
int left = 0;
int right = nums.size()-1;
while(left <= right){
int middle = (left + right) / 2;
if (nums[left] < nums[right]){
if (nums[middle] == target){
return middle;
}else if (nums[middle] > target){
right = middle - 1;
}else{
left = middle + 1;
}
}else{
if (nums[middle] == target){
return middle;
}else if (nums[middle] > target){
if (nums[middle] <= nums[right]){
right = middle - 1;
}else{
if (target <= nums[right]){
left = middle + 1;
}else{
right = middle - 1;
}
}
}else{
if (nums[middle] <= nums[right]){
if (target > nums[right]){
right = middle - 1;
}else{
left = middle + 1;
}
}else {
left = middle + 1;
}
}
}
}
return -1;
}
2)解决方案二代码
#include <iostream>
#include <vector>
using namespace std;
int search(vector<int>& nums, int target);
int main()
{
int a[] = {4,5,6,7,0,1,2};
vector<int> v;
for (int i=0; i<sizeof(a)/sizeof(a[0]); i++){
v.push_back(a[i]);
}
int result = search(v, 0);
cout << result << endl;
return 0;
}
int search(vector<int>& nums, int target){
int left = 0;
int right = nums.size()-1;
while(left < right){
int mid = (left + right) / 2;
if (nums[mid] > nums[right]){
left = mid+1;
}else{
right=mid;
}
}
int pivot = left;
left = 0;
right = nums.size() - 1;
while(left <= right){
int mid = (left + right) / 2;
int newmid = (mid + pivot) % nums.size();
if (target == nums[newmid]){
return newmid;
}else if (target > nums[newmid]){
left = mid+1;
}else{
right = mid-1;
}
}
return -1;
}