Search in Rotated Sorted Array

Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 01 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.

 

思路:本题还是在考察二分查找。在一个经过旋转后的数组中寻找某个值,首先需要找到“旋转点”,比如在数组 4 5 6 7 0 1 2中,0元素的索引,也就是4,即是我们需要首先找到的“旋转点”。找到旋转点之后,整个数组就分为两个子数组,一是旋转点之前的数组,另一个是旋转点之后的数组。这两个数组都是按序递增的,因此只要分别在这两个数组上使用二分查找即可。


如何寻找旋转点,也需要使用二分查找的变种,二分查找之所以这么快,就是因为它每次都去掉了一半的可能性。


在寻找旋转点时,还是要看中点的值set[mid],如果set[left]<=set[mid],set[right]<=set[mid],比如上例中的45 6 7 0 1 2,这说明当前的中点在旋转点的左边,因此需要left = mid+1。


如果set[left]>=set[mid],set[right]>=set[mid],比如6 7 0 1 2 4 5,这说明当前的中点在旋转点的右边,因此需要right = mid-1。


如果set[left]<=set[mid]<=set[right],则说明当前的left和right已经完全处于某个子数组之中了,这时就是结束寻找的时候了,因left或者right都是针对上次的mid值前进或后退一步得来的,说明left或者right就是该子数组的边界,具体哪个才是要找的旋转点,就看本次到底是left向前走还是right向后走得到的,代码如下:

int findrotate(int *sets, int nums)
{
	int left = 0, right = nums-1;
	int mid, lastmid = -1;

	while(left <= right)
	{
		mid = left + (right-left)/2;
		if(sets[left] <= sets[mid] && sets[mid] <= sets[right])	break;

		if(sets[mid] >= sets[left] && sets[mid] >= sets[right])
		{
			left = mid+1;
			lastmid = mid;
		}
		else
		{
			right = mid-1;
			lastmid = mid;
		}
	}

	if(mid < lastmid)	return lastmid;
	else 		return lastmid+1;
}

int search(int* nums, int numsSize, int target) 
{
	int left[2], right[2];
	int start, end, mid;
	left[1] = findrotate(nums, numsSize);
	left[0] = 0;
	right[0] = left[1]-1;
	right[1] = numsSize-1;

	int i = 0;
	for(i = 0; i < 2; i++)
	{
		start = left[i];
		end = right[i];
	
		while(start <= end)
		{
			mid = start + (end-start)/2;
			if(nums[mid] == target)	return mid;
			if(nums[mid] < target)
			{
				start = mid+1;
			}
			else
			{
				end = mid-1;
			}
		}
	}
	return -1;
}


原文地址:https://www.cnblogs.com/gqtcgq/p/7247145.html