您的位置:首页 > 其它

[LeetCode]25. Search in Rotated Array旋转数组查找I

2015-10-14 11:54 225 查看
Suppose a sorted array 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.

解法1:顺序查找,时间复杂度O(n)。

class Solution {
public:
int search(vector<int>& nums, int target) {
int n = nums.size(), i = 0;
while(i < n && target != nums[i])
i++;
return i == n ? -1 : i;
}
};


解法2:旋转数组是分为两个有序数组,因此可以使用二分查找。若数组首元素小于数组尾元素,则数组没有旋转,直接使用二分查找binarySearch即可;否则(1)初始化left=0,right=n-1,取mid=(left+right)/2;(2)如果target==nums[mid],则直接返回mid;否则若nums[left]<nums[mid],说明nums[left, ..., mid-1]是有序的,而nums[mid+1, ... , n-1]是旋转的,对前者调用binarySearch,若没找到再对后者调用search;若nums[left]>nums[mid],说明nums[left, ..., mid-1]是旋转的,而nums[mid+1, ... , n-1]是有序的,对后者调用binarySearch,若没找到再对前者调用search。

class Solution {
public:
int search(vector<int>& nums, int target) {
int n = nums.size();
if (n < 2)
return n == 1 ? (target == nums[0] ? 0 : -1) : -1;

int res, left = 0, right = n - 1;
if (nums[left] < nums[right])
res = binarySearch(nums, left, right, target);
else
{
int mid = (left + right) >> 1;
if (target == nums[mid])
res = mid;
else if (nums[left] < nums[mid])
{
if ((res = binarySearch(nums, left, mid - 1, target)) == -1)
{
vector<int> tmp(nums.begin() + mid + 1, nums.end());
res = search(tmp, target);
res = res == -1 ? -1 : res + mid + 1;
}
}
else
{
if ((res = binarySearch(nums, mid + 1, right, target)) == -1)
{
vector<int> tmp(nums.begin(), nums.begin() + mid);
res = search(tmp, target);
}
}
}
return res;
}
private:
int binarySearch(vector<int>& nums, int left, int right, int key)
{
if (left > right)
return -1;

int mid = (left + right) >> 1;
if (key == nums[mid])
return mid;
else if (key > nums[mid])
return binarySearch(nums, mid + 1, right, key);
else
return binarySearch(nums, left, mid - 1, key);
}
};


上面的代码可以进一步优化。首先根据nums[mid]和nums[right]的关系可以确定数组的哪部分是有序的:如果中间的数小于最右边的数,则右半段是有序的,若中间数大于最右边数,则左半段是有序的。然后再根据有序部分首尾两个数字和target的大小关系来判断target存在于哪一部分。

class Solution {
public:
int search(vector<int>& nums, int target) {
int n = nums.size();
int res = -1, left = 0, right = n - 1;

while(left <= right)
{
int mid = (left + right) >> 1;
if(target == nums[mid])
{
res = mid;
break;
}
else if(nums[mid] < nums[right]) //后半部分有序
{
if(target > nums[mid] && target <= nums[right])
left = mid + 1;
else
right = mid - 1;
}
else //前半部分有序
{
if(target >= nums[left] && target < nums[mid])
right = mid - 1;
else
left = mid + 1;
}
}
return res;
}
};


或者nums[mid]和nums[left]比较也可以,但是要注意mid=left的情况得单独拿出来讨论

class Solution {
public:
int search(vector<int>& nums, int target) {
int n = nums.size();
int res = -1, left = 0, right = n - 1;

while(left <= right)
{
int mid = ((left + right) >> 1);
if(target == nums[mid])
{
res = mid;
break;
}
else if(nums[mid] > nums[left]) //前半部分有序
{
if(target >= nums[left] && target < nums[mid])
right = mid - 1;
else
left = mid + 1;
}
else if(nums[mid] < nums[left]) //后半部分有序
{
if(target > nums[mid] && target <= nums[right])
left = mid + 1;
else
right = mid - 1;
}
else //nums[mid]==nums[left]的情况,包括mid=left和存在重复值两种情况
left++;
}
return res;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: