题目描述
题目分析
不含重复元素的题解(leetcode33)
这道题也是我们算法课的一道编程题,写完以后发现当时的思路和现在没有什么变化,果然是自己啊。我的想法是先判断区间整体是升序的还是旋转的,如果是升序的就按照正常的二分查找,如果是旋转的就判断中轴的落在了左半升区间还是右半升区间,问题的关键在于,旋转的数组不能简单因为target
和中轴的大小判断是在左区间还是右区间,因此要分类讨论一下。总之,这个思路不是很好,因为没有有效利用端点的信息,如同官方题解所说,我们是可以直接判断出target
在哪个区间的。每一次中轴会将数组分成两个部分,至少有一个部分是升序的,我们能够很简单的判断出target
是否在那个升序数组中,从而决定在哪个半区间中查找。
我的思路代码
class Solution {
public:int search(vector<int>& nums, int target) {return bsearch(nums, target, 0, nums.size());}
private:int bsearch(vector<int>& nums, int target, int l, int r) {if (l == r) return -1;int mid = (l + r) >> 1;if (nums[mid] == target) return mid;if (nums[l] <= nums[r - 1]) {//升序区间if (nums[mid] > target) return bsearch(nums, target, l, mid);else return bsearch(nums, target, mid + 1, r);} else {//旋转区间if (nums[mid] >= nums[l]) {//中心点落在左边升序区间if (nums[mid] < target) return bsearch(nums, target, mid + 1, r);else {int lr = bsearch(nums, target, l, mid);int rr = bsearch(nums, target, mid + 1, r);if (lr == -1) {if (rr == -1) return -1; else return rr;} else return lr;}} else {//中心点落在右边升序区间if (nums[mid] > target) return bsearch(nums, target, l ,mid);else {int lr = bsearch(nums, target, l, mid);int rr = bsearch(nums, target, mid + 1, r);if (lr == -1) {if (rr == -1) return -1; else return rr;} else return lr;}}}}
};
按照官方题解写的代码
class Solution {
public:int search(vector<int>& nums, int target) {int l = 0, r = nums.size(), mid;while (l < r) {mid = (l + r) >> 1;if (nums[mid] == target) return mid;if (nums[mid] >= nums[l]) {//左半区间是升序if (target >= nums[l] && target < nums[mid]) r = mid;else l = mid + 1;} else {//右半区间是升序if (target > nums[mid] && target <= nums[r - 1]) l = mid + 1;else r = mid;}}return -1;}
};
刚才看了一下题解,发现它总是和nums[0]
和nums[n-1]
比较,厉害。