二分查找题目

这篇博客探讨了二分查找算法在多种信息技术问题中的应用,包括查找数组中的特定元素、确定数字是否占多数、寻找数组中的不动点、猜数字游戏、找缺失正整数、目标下标定位、早餐组合计算、错误版本定位、采购方案优化以及排序数组操作等。通过这些实例展示了二分查找如何有效提高算法效率。
摘要由CSDN通过智能技术生成


检查一个数是否在数组中占绝大多数


在这里插入图片描述
在这里插入图片描述

class Solution {
    public int leftest(int[] nums,int target){
        int left=0,right=nums.length-1;
        int mid=0;
        while(left<right){
            mid=left+((right-left)>>1);
            if(nums[mid]>=target){
                right=mid;
            }
            else{
                left=mid+1;
            }
        }
        return left;
    }
    public int rightest(int[] nums,int target){
        int left=0,right=nums.length-1;
        int mid=0;
        while(left<right){
            mid=left+((right-left)>>1);
            if(nums[mid]>target){
                right=mid;
            }
            else{
                left=mid+1;
            }
        }
        return left;
    }
    public boolean isMajorityElement(int[] nums, int target) {
        
        //二分找出等于target最左的位置
        int left=leftest(nums,target);

        //二分找出等于target最右的位置
        int right=rightest(nums,target);
        if(left==right){
            return false;
        }
        return right-left+1>nums.length/2;
    }
}

在这里插入图片描述



不动点


在这里插入图片描述

在这里插入图片描述

class Solution {
    public int fixedPoint(int[] arr) {
        int left=0,right=arr.length-1;
        int mid=0;
        while(left<right){
            mid=left+((right-left)>>1);
            if(arr[mid]==mid){
                right=mid;
            }else if(arr[mid]<mid){
                left=mid+1;
            }else{
                right=mid-1;
            }
            
        }
        
        return left==arr[left]?left:-1;
    }
}

在这里插入图片描述



猜数字大小


在这里插入图片描述
在这里插入图片描述

/** 
 * Forward declaration of guess API.
 * @param  num   your guess
 * @return 	     -1 if num is lower than the guess number
 *			      1 if num is higher than the guess number
 *               otherwise return 0
 * int guess(int num);
 */

public class Solution extends GuessGame {
    public int guessNumber(int n) {
        
        int left=1,right=n;
        int mid=0;
        while(left<=right){
            mid=left+((right-left)>>1);
            if(guess(mid)==0)return mid;
            else if(guess(mid)>0){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
        return left;
    }
}

在这里插入图片描述

第 k 个缺失的正整数


在这里插入图片描述
在这里插入图片描述

class Solution {
    public int findKthPositive(int[] arr, int k) {
        int left=0,right=arr.length-1;
        if(arr[arr.length-1]==arr.length)return arr[arr.length-1]+k;
        if(arr[0]-1>=k){
            return k;
        }else{
            k-=(arr[0]-1);
        }
        
        int mid=0;
        while(left<right){
            mid=left+((right-left)>>1);
            if(left==mid)break;
            //if(k==0)break;
            else if(arr[mid]-arr[left]-(mid-left)>0){
                if(arr[mid]-arr[left]-(mid-left)<k){
                    k-=arr[mid]-arr[left]-(mid-left);
                    left=mid;
                }else{
                    right=mid;
                }    
            }else{
                left=mid;
            }
        }
        if(left<arr.length-1){
            if(arr[left]+1==arr[left+1]){
                return arr[arr.length-1]+k;
            }else{
                return arr[left+1]-arr[left]-1>=k?arr[left]+k:arr[left+1]+(k-(arr[left+1]-arr[left]-1));
            }
        }
        return arr[left]+k;
    }
}

在这里插入图片描述



找出数组排序后的目标下标


在这里插入图片描述

在这里插入图片描述

class Solution {
    public int leftest(int[] nums,int target){
        int left=0,right=nums.length-1;
        int mid=0;
        while(left<right){
            mid=left+((right-left)>>1);
            if(nums[mid]<target){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
        return left;
    }
    public int rightest(int[] nums,int target){
        int left=0,right=nums.length-1;
        int mid=0;
        while(left<right){
            mid=left+((right-left)>>1);
            if(nums[mid]<=target){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
        return left;
    }
    public List<Integer> targetIndices(int[] nums, int target) {
        Arrays.sort(nums);
        //二分找出等于target最左的位置
        int left=leftest(nums,target);
        //二分找出等于target最右的位置
        int right=rightest(nums,target);
        List<Integer>list=new ArrayList<>();
        for(int i=left;i<=right;++i){
            if(nums[i]==target){
                list.add(i);
            }
        }
        return list;

    }
}

在这里插入图片描述



早餐组合


在这里插入图片描述
在这里插入图片描述

class Solution {

    //O(NlogN)
    public int breakfastNumber(int[] staple, int[] drinks, int x) {
        //排序
        Arrays.sort(staple);
        Arrays.sort(drinks);
        int ans=0;
        int index=0;
        for(int s=0;s<staple.length;++s){
            if(staple[s]>=x)break;
            int rest=x-staple[s];
            //二分查找drinks数组中大于rest的最左的位置
            index=getIndex(drinks,rest);
            if(rest<drinks[index]){
                ans+=index;
            }else{
                ans+=index+1;
            }
            ans%=1000000007;
        }
        return ans%1000000007;
    }
    public int getIndex(int[] drinks,int x){
        int left=0,right=drinks.length-1;
        int mid=0;
        while(left<right){
            mid=left+((right-left)>>1);
            if(drinks[mid]>x){
                right=mid-1;
            }else{
                left=mid+1;
            }
        }
        return left;
    }
}

在这里插入图片描述



第一个错误的版本


在这里插入图片描述

在这里插入图片描述

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

public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        int left=1,right=n;
        int mid=0;
        while(left<=right){
            mid=left+((right-left)>>1);
            if(isBadVersion(mid)){
                right=mid-1;
            }else{
                left=mid+1;
            }
        }
        return left;
    }
}

在这里插入图片描述



采购方案

在这里插入图片描述

在这里插入图片描述

class Solution {
    
    //先排序再二分
    public int fun(int[] nums,int target){
        Arrays.sort(nums);
        int ans=0;
        for(int i=0;i<nums.length-1;++i){
            if(nums[i]>=target)break;
            //二分找到比target-nums[i]大的最左位置
            int index=getIndex(nums,target-nums[i],i+1,nums.length-1);
            if(target-nums[i]>=nums[index]){
                ans+=(index-i);
            }else{
                ans+=(index-i-1);
            }
            ans%=1000000007;
        }
        return ans%1000000007;
    }
    public int getIndex(int[] nums,int x,int left,int right){
        if(left==right)return left;
        int mid=0;
        while(left<right){
            mid=left+((right-left)>>1);
            if(nums[mid]>x){
                right=mid-1;
            }else{
                left=mid+1;
            }
        }
        return left;
    }
    public int purchasePlans(int[] nums, int target) {
        // return process(nums,0,2,target);
        // return DP(nums,target);
        return fun(nums,target);
    }
}

在这里插入图片描述



和为s的两个数字

在这里插入图片描述

class Solution {
    public int index(int[] nums,int x,int left,int right){
        int mid=0;
        while(left<right){
            mid=left+((right-left)>>1);
            if(nums[mid]==x)return mid;
            else if(nums[mid]<x){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
        return left;
    }
    public int[] twoSum(int[] nums, int target) {
        int[] ans=new int[2];
        for(int i=0;i<nums.length-1;++i){
            int cur=index(nums,target-nums[i],i+1,nums.length-1);
            if(target-nums[i]==nums[cur]){
                ans[0]=nums[i];
                ans[1]=target-nums[i];
                break;
            }
        }
        return ans;
    }
}

在这里插入图片描述



排序数组中两个数字之和

在这里插入图片描述

在这里插入图片描述

class Solution {
    public int index(int[] numbers,int x,int left,int right){
        int mid=0;
        while(left<right){
//        	System.out.println(left+" "+right);
        	mid=left+((right-left)>>1);
            if(numbers[mid]==x)return mid;
            else if(numbers[mid]<x){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
        return left;
    }
    public int[] twoSum(int[] numbers, int target) {

        int[] ans=new int[2];
        int cur=0;
        for(int i=0;i<numbers.length-1;++i){
        	
            cur=index(numbers,target-numbers[i],i+1,numbers.length-1);
            
            if(numbers[cur]==target-numbers[i]){
                ans[0]=i;
                ans[1]=cur;
                break;
            }
        }
        return ans;
    }
}

在这里插入图片描述



查找插入位置

在这里插入图片描述

在这里插入图片描述


class Solution {
    public int searchInsert(int[] nums, int target) {

        int left=0,right=nums.length-1;
        int mid=0;
        while(left<=right){
            mid=left+((right-left)>>1);
            if(nums[mid]==target)return mid;
            else if(nums[mid]<target){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
        return left;
    }
}

在这里插入图片描述



山峰数组的顶部

在这里插入图片描述

在这里插入图片描述

class Solution {

    //O(N)解法
    public int process1(int[] arr){
        for(int i=0;i<arr.length-1;++i){
            if(arr[i]>arr[i+1]){
                return i;
            }
        }
        return 0;
    }
    //O(longN)解法
    //二分查找
    public int process2(int[] arr){
        int left=0,right=arr.length-1;
        int mid=0;
        while(left<=right){
            mid=left+((right-left)>>1);
            if(mid==0){
                left=mid+1;
            }
            else if(mid==arr.length-1){
                right=mid-1;
            }
            else if(arr[mid]>arr[mid-1]&&arr[mid]>arr[mid+1]){
                return mid;
            }else if(arr[mid]>arr[mid-1]&&arr[mid]<arr[mid+1]){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
        return 0;
    }
    public int peakIndexInMountainArray(int[] arr) {
        // return process1(arr);
        return process2(arr);
    }
}

在这里插入图片描述



求平方根

在这里插入图片描述

class Solution {
    public int mySqrt(int x) {
        if(x==0||x==1)return x;
        long left=1,right=x/2;
        long mid=left+((right-left)>>1);
        while(left<=right){
            mid=left+((right-left)>>1);
            if(mid*mid==x){
                break;
            }
            else if(mid*mid<x){
                if((mid+1)*(mid+1)>x)break;
                left=mid+1;
            }
            else{
                right=mid-1;
            }
        }
        return (int)mid;
    }
}

在这里插入图片描述



最接近的二叉搜索树值


在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    
    public int closestValue(TreeNode root, double target) {
        TreeNode cur=root;
        int ans=0;
        double min=Integer.MAX_VALUE;
        while(cur!=null){
            if(min>=Math.abs(cur.val-target)){
                min=Math.abs(cur.val-target);
                ans=cur.val;
            }
            if(target<cur.val){
                cur=cur.left;
            }else{
                cur=cur.right;
            }
        }
        
        return ans;
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值