题目出处:https://leetcode.com/problems/search-in-rotated-sorted-array-ii/
题意描述:
给定一循环数组,查找目标值是否在该数组中。
解决思路:
由于这是Search in Rotated Sorted Array的后续题目,因此我想为了解决这道题我们有必要先解决上一道题。也就是不重复的情况下的查找。由于数组不重复,因此我们只需要先找出突变的位置即可调用经典的二分查找。而查找突变位置也可以通过二分的方式给出。附代码如下(其中find_mid函数为寻找突变点的函数,binary_search为普通的二分查找,search在调用find_mid获得突变点的位置后调用binary_search查找并获取结果)。
1 class Solution { 2 public: 3 int find_mid(vector<int>& nums, int l, int r) 4 { 5 if(l == r) 6 return r; 7 int pos = (r+l)/2; 8 if(nums[pos] >= nums[0] && nums[pos+1] < nums[0]) 9 return pos; 10 else if(nums[pos] < nums[0]) 11 return find_mid(nums, l, pos-1); 12 else 13 return find_mid(nums, pos+1, r); 14 }; 15 16 int binary_search(vector<int>& nums, int target, int l, int r) 17 { 18 if(l > r) 19 return -1; 20 21 int mid = (l+r)/2; 22 if(nums[mid] == target) 23 return mid; 24 else if(nums[mid] < target) 25 return binary_search(nums, target, mid+1, r); 26 else 27 return binary_search(nums, target, l, mid-1); 28 } 29 30 int search(vector<int>& nums, int target) { 31 int mid = find_mid(nums, 0, nums.size()-1); 32 if(nums[0] > target) 33 { 34 if(mid < nums.size()-1) 35 return binary_search(nums, target, mid+1, nums.size()-1); 36 else 37 return -1; 38 } 39 else 40 return binary_search(nums, target, 0, mid); 41 }; 42 };
上述代码在OJ果断AC,将这道题解决后,我们只需要将之修改为可处理重复情况即可。首先我们尝试将上述代码的稍作修改提交试试效果。修改后的代码如下:
1 class Solution { 2 public: 3 int find_mid(vector<int>& nums, int l, int r) 4 { 5 if(l == r) 6 return r; 7 int pos = (r+l)/2; 8 if(nums[pos] >= nums[0] && nums[pos+1] < nums[0]) 9 return pos; 10 else if(nums[pos] < nums[0]) 11 return find_mid(nums, l, pos-1); 12 else 13 return find_mid(nums, pos+1, r); 14 }; 15 16 int binary_search(vector<int>& nums, int target, int l, int r) 17 { 18 if(l > r) 19 return -1; 20 21 int mid = (l+r)/2; 22 if(nums[mid] == target) 23 return mid; 24 else if(nums[mid] < target) 25 return binary_search(nums, target, mid+1, r); 26 else 27 return binary_search(nums, target, l, mid-1); 28 } 29 30 bool search(vector<int>& nums, int target) { 31 int mid = find_mid(nums, 0, nums.size()-1); 32 int pos; 33 if(nums[0] > target) 34 { 35 if(mid < nums.size()-1) 36 pos = binary_search(nums, target, mid+1, nums.size()-1); 37 else 38 pos = -1; 39 } 40 else 41 pos = binary_search(nums, target, 0, mid); 42 return (pos != -1); 43 }; 44 };
果然,上述代码跪了,对样例分析可知,在首位和中间的值均相等时,函数无法确定突变点在左半区间还是右半区间。于是我们需要对此特殊情况进行处理。我的做法是判定这三个值均相等时修改上界或下界,再递归调用函数求解。代码如下:
1 class Solution { 2 public: 3 int find_mid(vector<int>& nums, int l, int r) 4 { 5 if(l == r) 6 return r; 7 int pos = (r+l)/2; 8 if(nums[pos] >= nums[0] && nums[pos+1] < nums[0]) 9 return pos; 10 else if(nums[pos] < nums[0]) 11 return find_mid(nums, l, pos-1); 12 else if(nums[pos] > nums[0]) 13 return find_mid(nums, pos+1, r); 14 else 15 { 16 if(nums[r] == nums[pos]) 17 r --; 18 else 19 l ++; 20 return find_mid(nums, l, r); 21 } 22 }; 23 24 int binary_search(vector<int>& nums, int target, int l, int r) 25 { 26 if(l > r) 27 return -1; 28 29 int mid = (l+r)/2; 30 if(nums[mid] == target) 31 return mid; 32 else if(nums[mid] < target) 33 return binary_search(nums, target, mid+1, r); 34 else 35 return binary_search(nums, target, l, mid-1); 36 } 37 38 bool search(vector<int>& nums, int target) { 39 int mid = find_mid(nums, 0, nums.size()-1); 40 int pos; 41 if(nums[0] > target) 42 { 43 if(mid < nums.size()-1) 44 pos = binary_search(nums, target, mid+1, nums.size()-1); 45 else 46 pos = -1; 47 } 48 else 49 pos = binary_search(nums, target, 0, mid); 50 return (pos != -1); 51 }; 52 };
上述代码获得了AC。OK,吃饭去了。