https://leetcode-cn.com/problems/search-in-rotated-sorted-array/
《剑指offer》题,二分搜索找特殊条件,感觉书上描述的很简单,(可能之前做过所以觉得简单点。。)
对于一个升序排序的数组,从某个位置截断,然后直接拼在后面。看题目给的例子,还是比较直白的。
其实题本身不难,做了一些中等难度的题,其实大部分都没啥难度,简单题反而有一些比较骚的。中等题很多都坑在略考验码速,有一个大数乘法、螺旋数组的模拟等等,这个题也一样,撸一堆代码,出一点错就很蛋疼。
看评论有人吐槽直接遍历也能搜出来答案= =因为要求时间复杂度是O(logn),并且是已经升序排序的数组了,只是中间截断了而已。那么反过来,如果从截断点开始分成两个数组,那么对于单个数组就可以使用二分搜索了,而二分搜索恰是O(logn)的时间复杂度。
问题就是如何找到截断点。很明显,如果没有截断点的话,直接升序,对于i而言:arr[i-1] < arr[i] < arr[i+1]这个等式是恒成立的,题也说了不存在重复。如果存在i:arr[i - 1] > arr[i] || arr[i] > arr[i+1],那么i就是截断点,并且属于后半数组。所以,找到截断点就是比较重要了。for循环遍历就有点蛋疼了,仍然使用二分,可以先找截断点。找到以后就将数组分成左右两部分,分别使用二分搜索即可。
这个题情况非常多,所以剪枝能写很多。例如分开二分搜索的时候,如果第一个数组就搜到答案了,那么第二组就可以不搜索了。如果在搜截断点的时候就找到答案,那么就可以直接结束了。等等。
另外我的代码是忽略了数组元素小于3的数据,这些单独拿出来计算了。主要是交的时候发现WA了,所以就拿出来单独算。可能是搜截断点的时候,数组元素是2的时候各种越界吧,懒得写了,所以就直接判断了特殊情况= =。
class Solution {
public static int flag;
public static int len;
public static int ans;
public static void search(int left,int right,int[] nums){
if(left == right) return;
int mid = (left+right)/2;
if(mid == 0){
if(nums[mid] > nums[mid+1]){
flag = mid;
return;
}
}else{
if(mid == len-1){
if(nums[mid] < nums[mid-1]){
flag = mid;
return;
}
}else{
if(nums[mid] > nums[mid+1] || nums[mid] < nums[mid-1]){
flag = mid;
return;
}
}
}
search(left,mid,nums);
if(flag != -1) return;
search(mid+1,right,nums);
}
public static void brain(int left,int right,int[] nums,int target){
if(left == right){
if(target == nums[left]){
ans = left;
}
return;
}
int mid = (left+right)/2;
if(target == nums[mid]){
ans = mid;
return;
}
if(target > nums[mid]){
brain(mid+1,right,nums,target);
}else{
brain(left,mid,nums,target);
}
}
public int search(int[] nums, int target) {
flag = -1;
ans = -1;
len = nums.length;
if(len == 0) return -1;
if(len == 1){
if(target == nums[0]) return 0;
return -1;
}
if(len == 2){
for(int i = 0;i < 2;i++){
if(target == nums[i]) return i;
}
return -1;
}
search(0,len-1,nums);
if(flag == -1){
brain(0,len-1,nums,target);
return ans;
}
if(nums[flag] == target) return flag;
brain(0,flag,nums,target);
if(ans != -1) return ans;
brain(flag+1,len-1,nums,target);
return ans;
}
}