leetcode 33和 leetcode81 II
//接上上一篇博客,继续这个题目,现在数组中会有重复元素,情况将会变得十分复杂,比如说1,1,1,1,1 或者1,1,3,1再来 3,3,3,1,1,1,3,这些都是可以的,都是符合题目要求的,如果有疑问,自己想想。那么这么复杂怎么找最大点呢?我找不到,我去看了我牛客网当时的思路,当时找的是最小值,我觉得没问题,我就这么找了。
下面给出代码:
class Solution { public boolean search(int[] nums, int target) { if(nums==null||nums.length==0) return false; if(nums.length==1) return target==nums[0]?true:false; int l=0; int r=nums.length-1; int i=find(nums,l,r); while(i-1>=0&&nums[i-1]==nums[i]) i--; if(binarySearch(nums,l,i-1,target)!=-1||binarySearch(nums,i,r,target)!=-1) return true; else return false; } public int binarySearch(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 find(int[] nums,int l,int r) { while(l<=r) { if(nums[l]<nums[r]) return l; int mid=l+(r-l)/2; if(nums[mid]>nums[l]) l=mid+1; else if(nums[mid]<nums[r]) r=mid; else l++; } return r; } }
将核心代码拿出来
public int find(int[] nums,int l,int r)
{
while(l<=r)
{
if(nums[l]<nums[r])
return l;
int mid=l+(r-l)/2;
if(nums[mid]>nums[l])
l=mid+1;
else if(nums[mid]<nums[r])
r=mid;
else
l++;
}
return r;
}
对于nums[l]<nums[r],因为现在有重复元素,所以不能加等号,比如说2,2,1,2,不能直接判断了,然后还是求出mid,因为现在我们找最小值了,所以我们右边的就不要动,这里的动指的是+1或者不加
1,直接等于mid,移动l=mid+1,不会错过最小值,可能会错过最大值。如果num[mid]>nums[l],说明现在mid左边是上升的,直接让l=mid+1,如果nums[mid]<nums[r],说明右边是上升的,所以我们
直接r=mid;如果都不满足,进入最后一个else,说明现在遇到了相等值,现在就不能用二分去判断了,只能慢慢的移动一个个来,让l++,这样的话,我们r不会移动,所以不会导致我们错过最小值,直到l移动
过了r,结束循环,返回我们的r,记住很关键的一点,这个r现在是我们找到的最右边的那个最小值,所以当你返回以后,还是需要处理的。
这种情况只有右边全是最小值的时候才会发生,3,1,1,1的时候是最后的一个1,但是如果是3,1,1,1,3返回的就是第一个1了,感觉很奇妙。现在下课了,那么就写到这吧。有什么问题,可以讨论。