二分查找就是通过判断来舍去错误区间,从而通过排除逼近得到结果,本题中,当nums[mid]==target时不应该停下脚步(跳出循环),因为需要寻找最左(以及最右)边的那个target。所以当 nums[mid]==target时区间继续向左逼近,即left=mid-1;那么如果错过了taget怎么办?可以在left=mid-1;语句前加上first_place=left;保存目前位置最左边的满足 nums[mid]==target的位置。同理再对找出最右边的满足nums[mid]==target的位置进行一次二分查找即可。
class Solution {
public int[] searchRange(int[] nums, int target) {
int left=0;
int right=nums.length-1;
int first_place=-1;
int last_place=-1;
while(left<=right){
int mid = left+(right-left)/2;
if(nums[mid]<target)
left=mid+1;
else if(nums[mid]>target)
right=mid-1;
else {
first_place=mid;
right=mid-1;
}
}
left=0;
right=nums.length-1;
while(left<=right){
int mid = left+(right-left)/2;
if(nums[mid]<target)
left=mid+1;
else if(nums[mid]>target)
right=mid-1;
else {
last_place=mid;
left=mid+1;
}
}
return new int[]{first_place,last_place};
}
}
这题使用二分法,二分法的本质就是通过条件排除一半的区间,从而将区间逼近至有限的容易判断的区间。mid=left+(right-left)/2;通过什么条件来排除一半的区间呢?据题意,如果nums[mid-1]、nums[mid]、nums[mid+1].递增的话,那山顶必在mid+1--right部分,同理如果三者递减,那么山顶必在left--mid-1部分。如果nums[mid-1]<nums[mid]>nums[mid+1].直接return。另外还需要考虑数组边界溢出情况。
class Solution {
public int peakIndexInMountainArray(int[] arr) {
int left=0;
int right=arr.length-1;
while(left<=right){
int mid=left+(right-left)/2;
if(mid-1>=0&&mid+1<arr.length){
if(arr[mid-1]<arr[mid]&&arr[mid]<arr[mid+1])
left=mid+1;
else if(arr[mid-1]>arr[mid]&&arr[mid]>arr[mid+1])
right=mid-1;
else if(arr[mid-1]<=arr[mid]&&arr[mid]>=arr[mid+1])
return mid;
}
else if(mid==0)
left++;
else if(mid==arr.length-1)
right--;
}
return right;
}
}
本题使用二分法,二分法的本质就是通过条件排除一半区间从而逐渐缩小正确答案所在的区间。
本题通过什么条件来排除一半区间呢?旋转数组有一个特性,如果nums[a]<num[b](a<b).那么nums在a,b单调递增。本题要寻找最小值,如果nums[left]<nums[mid]那么nums在left--mid递增,最小值不会在这段区间里。则left=mid+1;相反,如果nums[left]>nums[mid]则区间内不单调,那么单调区间一定在另一半区间。正确答案一定在本区间。当然还要考虑特殊情况,旋转数组为原数组情况下直接返回第一个元素值就行。
class Solution {
public int findMin(int[] nums) {
int left=0;
int right=nums.length-1;
int min=-1;
if(nums[left]<nums[right])
return nums[left];
while(left+1<right){
int mid =left+(right-left)/2;
if(nums[left]<nums[mid])
left=mid;
else{
right=mid;
}
}
if(nums[left]<nums[right])
return nums[left];
else
return nums[right];
}
}
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
if(root==null)
return null;
if(root.val==val)
return root;
TreeNode ans=null;
if(root.val>val)
ans=searchBST(root.left,val);
if(root.val<val)
ans=searchBST(root.right,val);
return ans;
}
}
class Solution {
long pre=Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
if(root==null)
return true;
boolean ans1=isValidBST(root.left);
if(root.val<=pre)
return false;
pre=(long)root.val;
boolean ans2=isValidBST(root.right);
return ans1&&ans2;
}
}