题目:
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、两次二分查找:第一次二分查找的目标是找出数组具体在哪个位置做了旋转,这个可以简单地通过比较nums[mid]和它的相邻元素的大小实现。第二次二分查找就简单了:先判断待查找值在左半部分还是右半部分,然后调用普通的二分查找进行查询。
2、一次二分查找:由于数组中没有重复元素,所以思路1中的第一次二分查找其实是不必要的。设中位数为nums[mid],则一次二分查找的思路如下:
1)如果nums[mid] == target,则直接返回mid;
2)如果nums[mid] < nums[right],则说明从mid到right之间是严格递增的。此时可以方便地判断target是否在这一递增区间内:如果是,则在这一递增区间内查找;否则就在另外一个递增区间内找。
3)如果nums[mid] > nums[right],则说明从left到mid之间是严格递增的。此时可以方便地判断target是否在这一递增区间内:如果是,则在这一递增区间内查找;否则就在另外一个递增区间内找。
注意在下面的代码中,即使已经判断出某一区间为严格递增区间了,我们还是用了自己设计的针对旋转排序数组的查找方法。事实上,此时我们可以直接调用标准的二分查找方法,速度应该会更快一些(建议读者自己设计并实现)。
代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.size() == 0) return -1;
int left = 0, right = nums.size() - 1;
while(left <= right)
{
int mid = left + (right - left) / 2;
if(nums[mid] == target)
{
return mid;
}
else if(nums[mid] < nums[right]) // the right part is increasing
{
if(nums[mid] < target && target <= nums[right])
left = mid + 1; // might be improved by binarySearch
else
right = mid - 1;
}
else // the left part is increasing
{
if(nums[left] <= target && target < nums[mid])
right = mid - 1; // might be improved by binarySearch
else
left = mid + 1;
}
}
return -1;
}
};Follow up:
如果允许数组中有重复元素呢?此时就不能通过判断相互大小每次使搜索空间减半了。具体解法请参考Leetcode 81。
这篇博客介绍了如何解决LeetCode上的33题——在一个已旋转的有序数组中搜索目标值。文章详细阐述了两种解题思路:1) 两次二分查找,首先找到旋转点,然后在确定的区间内进行普通二分查找;2) 一次二分查找,通过比较中位数和边界值判断目标值所在区间。代码示例展示了具体的实现方法,并提醒读者在确定递增区间后可直接使用标准二分查找以提高效率。此外,博主还指出当数组允许重复元素时,需要采用不同的解法,如LeetCode 81题的解法。

2027

被折叠的 条评论
为什么被折叠?



