二分查找

二分法难点:数据索引的更新

/* The isBadVersion API is defined in the parent class VersionControl.
      boolean isBadVersion(int version); */

public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        /*如果第m个错误的版本出现错误,那么第一个出现错误的版本[l.m]之间  h=m;
        如果第m个错误的版本不是错误,那么第一个出现错误的版本[m+1.h]之间 l=m+1;
        由于h=m;所以循环条件l<h;否则会出先死循环现象
        */
        int l=1;
        int h=n;
        while(l<=h){
            int m=l+(h-l)/2;
            if(isBadVersion(m)==true){
                h=m-1;
            }else{
                l=m+1;
            }
        }
        return l;
    }
}

查找只出现一次的那个元素

class Solution {
    public int singleNonDuplicate(int[] nums) {
        /*考虑用二分法思想
        设单个元素出现的索引为index;设m为偶数,在m+1<index时候,nums[m]==nums[m+1];
        在m+1>index时候,nums[m]!=nums[m+1]
        依据这个原则来进行索引的更新
        */
        int l=0;
        int h=nums.length-1;
        while(l<h){
            int m=l+(h-l)/2;
            if(m%2==1){
                m--;
            }//保证是偶数索引,访问到的区间都是奇数区间
            if(nums[m]==nums[m+1]){
                //索引index在后半段[m+2,h]
                l=m+2;
            }else{
                //索引在前半段[l,m]
                h=m;
            }
        }
        return nums[l];
    }
}

查找给定目标元素第一次和最后一次出现的位置 

class Solution {
    public int[] searchRange(int[] nums, int target) {
       int firstIndex= searchFirstIndex(nums,  target);
       int lastIndex =searchFirstIndex( nums,  target+1)-1;
        //1.索引都是有效值,不为空,
        if(firstIndex==nums.length||nums[firstIndex]!=target){
             return new int[]{-1,-1};
        }else {
            return new int[] {firstIndex,Math.max(firstIndex,lastIndex)};
        }
        
    }
    private int searchFirstIndex(int[] nums, int target){
        int l=0;
        int h=nums.length;
        while(l<h){
            int m=l+(h-l)/2;
            if(nums[m]>=target){
                h=m;
            }else{
                l=m+1;
            }
        }
        return l;
    } 
    
}

旋转数组中的最小元素

class Solution {
    public int findMin(int[] nums) {
        /*1.利用二分查找*/
        int l=0;
        int h=nums.length-1;
        while(l<h){
            int m=l+(h-l)/2;
            //如果中间元素大于第一个l,小于后一个元素,那么最小的元素一定在后半段区间
           if(nums[m]<=nums[h]){
               h=m;
           }else{
               l=m+1;
           }
        }
        return nums[l];
    }
}

 

class Solution {
    public int[] searchRange(int[] nums, int target) {
       int[] result = new int[2];
        result[0]= searchFirstIndex(nums, target);
        result[2]=searchLastIndex(nums, target);
       return result;
    }
    private int searchFirstIndex(int[] nums, int target){
        int firstIndex=-1;
        int l=0;
        int h=nums.length-1;
        while(l<h){
            int m=l+(h-l)/2;
            if(nums[m]>=target){
                h=m;
            }else{
                l=m+1;
            }
        }
        if(nums[l]==target) firstIndex=l;
        return firstIndex;    
    } 
    
    //最后一次出现的位置
     private int searchLastIndex(int[] nums, int target){
        int lastIndex=-1;
        int l=0;
        int h=nums.length-1;
        while(l<h){
            int m=l+(h-l)/2;
            if(nums[m]<=target){
                l=m;
            }else{
                h=m-1;
            }
           
        }
        if(nums[l]==target) lastIndex=l;
        return lastIndex;
    } 
}
class Solution {
    public int[] searchRange(int[] nums, int target) {
       int[] result = {-1,-1};
       result[0]= searchFirstIndex(nums, target);
        //如果查找到了一个索引,在继续查找是否有其他的索引
        if(result[0]!=-1){
            result[1]=searchLastIndex(nums, result[0],target);
        } 
       return result;
    }
    //第一次出现的位置
    private int searchFirstIndex(int[] nums, int target){
        int firstIndex=-1;
        int l=0;
        int h=nums.length-1;
        while(l<=h){
            int m=l+(h-l)/2;
            if(nums[m]>target){
                h=m-1;
            }else if(nums[m]<target){
                l=m+1;
            }else{
                firstIndex=m;
                h=m-1;
            }
        }
        return firstIndex;    
    }  
    //最后一次出现的位置
     private int searchLastIndex(int[] nums, int left,int target){
        int lastIndex=-1;
        int l=left;
        int h=nums.length-1;
        while(l<=h){
            int m=l+(h-l)/2;
            if(nums[m]>target){
                h=m-1;
            }else if(nums[m]<target){
                l=m+1;
            }else{
                lastIndex=m;
                l=m+1;
            }
        }
        return lastIndex;
    } 
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值