算法通关村--第九关白银挑战

二分查找就是通过判断来舍去错误区间,从而通过排除逼近得到结果,本题中,当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;
    }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值