//感想:
1.对于这两题,我真的是做到吐,这篇博客本来是昨晚准备写的,但是对于这个第二题,我真的做到头痛,实在是太尼玛的吐血了,主要是我也是头铁,非要找到那个分界点。
2.其实之前在牛客网上做过非常类似的题目,当时就做的特别痛苦,后来做完也没总结,导致现在做又不知道思路了,不过好歹留下了代码,再次做的时候,看看之前的代码,再结合这道题目的要求也是做完了。
思路:对于33题。
题目要求要logn的,我们对自己要求也要严格一点,所有的都用二分来做,这题目其实是变种的二分,因为正常的二分是找寻一个target值,但是我们现在不是找一个target,而是去找这个排序数组的分界点,对于没有重复元素的,就比较容易了,
所以它只有这种类型,找分界点还是比较容易的。无论是找最大的,还是最小的,都是可以的,这里的二分法要格外注意左右两边的边界移动情况。这是找的最大值的下标,来看看这个helper函数
while(l<=r) { if(nums[l]<=nums[r]) return r; int mid=l+(r-l)/2; if(nums[mid]>nums[l]) l=mid; else r=mid-1; } return l;
首先如果nums[l]<=nums[r],那么这直接就是一条斜线,可以直接返回右边界,如果nums[mid]>nums[l],说明还在上升,移动左下标指向mid,记住
现在找的是最大值,所以不能让l=mid+1,而是等于mid,不然可能会错过最大值,else 直接让r=mid-1,因为不在上升就肯定在下边,所以直接等于
就行了,继续这样循环,直到右边界移出左边界,那时候我们返回l就行了。感觉还是可以的,主要是情况没有那么复杂,下面就是下一题,原本想做一篇
写的,但是感觉写的太臃肿了,还是在写一篇吧。
class Solution { public int search(int[] nums, int target) { if(nums==null||nums.length==0) return -1; if(nums.length==1) return target==nums[0]?0:-1; int l=0; int r=nums.length-1; int i=helper(nums,l,r); if(target>=nums[0]) return helper1(nums,l,i,target); else return helper1(nums,i+1,r,target); } public int helper1(int[] nums,int l,int r,int target) { while(l<=r) { int mid=l+(r-l)/2; if(nums[mid]==target) return mid; else if(nums[mid]>target) r=mid-1; else l=mid+1; } return -1; } public int helper(int[] nums,int l,int r) { while(l<=r) { if(nums[l]<=nums[r]) return r; int mid=l+(r-l)/2; if(nums[mid]>nums[l]) l=mid; else r=mid-1; } return l; } }