力扣 题目33-- 搜索旋转排序数组
题目
题解
这题其实直接做还是比较简单的 找到旋转点 判断一下二分查找即可 但是不满足进阶的条件
进阶:你可以设计一个时间复杂度为 O(log n) 的解决方案吗?
看到O(log n) 我们就能想到二分查找 但是二分查找是有序的才能使用
由于nums是部分有序 那么我们能不能拆一下呢?即 以中间位置拆开
4,5,6,7,0,1,2->4,5,6,7 0,1,2 然后用目标值0比较一下最大和最小 发现应该是右边 然后用右边去二分查找
但是这是特殊情况 还有情况是这种
4,5,6,7,8,9,0,1,2->4,5,6,7,8 9,0,1,2这样的话显然 我们无法确定取哪个进行二分查找
但是左边已经是有序 用上面的比较方法发现 应该不是我们要找的范围 那么直接舍弃
现在看右边 继续重复上面步骤 9,0,1,2 ->9, 0 1,2 右边有序 但是判断之后不是范围 舍弃
9,0->9 0 这样就都是有序的了 放入二分搜索查找即可
一句话总结:将无序 分割变 有序 进行二分搜索
代码
1 #include<iostream> 2 #include<vector> 3 using namespace std; 4 //二分搜索 5 int ersearch(vector<int>& nums,int target,int left,int right) 6 { 7 while (left <= right) { 8 int middle = left + ((right - left) / 2); 9 if (nums[middle] > target) { 10 right = middle - 1; 11 } 12 else if (nums[middle] < target) { 13 left = middle + 1; 14 } 15 else { 16 return middle; 17 } 18 } 19 return -1; 20 } 21 //分割 22 int division(vector<int>& nums,int left, int right,int target) 23 { 24 //找到中心位置 25 int middle = left+((right - left) / 2); 26 int num = -1; 27 //如果第一个比最后一个大 那么无序 需要分割 28 if (nums[left] > nums[right]) { 29 //递归方法 以中心点进行分割 左 30 num=division(nums,left, middle, target); 31 //返回的如果不是-1 那么就是在之后的调用中找到了位置 需要返回 32 if (num != -1) { 33 return num; 34 } 35 //递归方法 以中心点进行分割 右 36 num=division(nums,middle+1,right, target); 37 //返回的如果不是-1 那么就是在之后的调用中找到了位置 需要返回 38 if (num != -1) { 39 return num; 40 } 41 } 42 //如果第一个比最后一个小 那么有序 范围判断后进行二分搜索 43 else 44 { 45 //判断target是否在这个范围内 46 if (target <= nums[right] && target >= nums[left]) { 47 return ersearch(nums, target, left, right); 48 } 49 else 50 { 51 return -1; 52 } 53 } 54 return -1; 55 } 56 class Solution { 57 public: 58 int search(vector<int>& nums, int target) { 59 //调用分割函数 60 int position=division(nums,0, nums.size()-1, target); 61 cout << position << endl; 62 return position; 63 } 64 }; 65 int main() { 66 vector<int>nums = { 5,4}; 67 int target = 4; 68 Solution sol; 69 sol.search(nums, target); 70 }