这道题在LeetCode上是Hard类的,首先声明,代码是别人的,我只是解释一下。
class Solution { public: /* 如果数组是有序的,那么大家都会想到并使用二分搜索,但本题设置了这样一个障碍:数组是rotate过的。这样,原先有序的数组就变成了局部有序:(假设)分为两个有序的子数组,并且左边子数组中的元素都大于右边子数组中的元素。这时,采用二分搜索,需要判断数组nums[left..right]和下标mid分别处于什么位置。分为以下2种情况: 1.nums[mid] >= nums[left] 这时可判断下标left和mid处于同一个子数组的下标范围中,至于right,未知。我们现在要确定,是到左半边数组即nums[left..mid-1]中继续搜索,还是到右半边数组nums[mid+1..right]中搜索。 到右半边数组搜索有两种情况,一是target>nums[mid],这个很自然,依据是二分搜索的基本原理;二是target<nums[left],这说明target不在整个原数组即nums[0..nums.size()-1] rotate后的左半边有序数组里,而在右边的有序子数组里。这两种情况只要满足其中一种,就到nums[mid+1..right]中继续搜索,而不用管nums[left..mid-1],因此令left = mid+1; 2.nums[mid] < nums[left] 这时可判断下标left在左半边有序数组中,mid在右半边有序数组中。此时若要到nums[mid+1..right]中搜索,需同时满足两个条件:①target>nums[mid],这个也很自然,无须解释,但要注意,别忘了第二个条件:②target<=nums[right],否则target就不在这部分的有序子数组中了,必须到左半边有序数组中搜索(在常规的二分搜索中若target>nums[right]即可判定无解,搜索失败,而在本题条件下,target可能存在于被rotate到数组前半部分的子数组中,还须进一步搜索)。 综上,在(nums[mid]>=nums[left] && (target>nums[mid] || target<nums[left])) || (nums[mid]<nums[left] && target>nums[mid] && target<=nums[right])为真时令left = mid+1,到nums[mid..right]中搜索,否则令right = mid-1,到nums[left..mid-1]中寻找。 */ int search(vector<int>& nums, int target) { if(nums.size() == 0) return -1; int left = 0; int right = nums.size()-1; while(left <= right){ int mid = (left+right)/2; if(target == nums[mid]) return mid; if((nums[mid]>=nums[left] && (target>nums[mid] || target<nums[left])) || (nums[mid]<nums[left] && target>nums[mid] && target<=nums[right])) left = mid + 1; else right = mid -1; } return -1; } };
Search in Rotated Sorted Array——LeetCode
原文地址:http://blog.csdn.net/hh794362661/article/details/46626801