首页 > 其他分享 >二分法

二分法

时间:2023-06-05 19:12:48浏览次数:44  
标签:right target nums int 二分法 数组 left

使用条件

  1. 有序数组
  2. 元素不重复

区间设置

  1. 左闭右闭:
    • 左右区间边界都要在数组的索引有效范围内(left=0,right=数组长度-1)
    • 判断条件 left(左边界)<=right(右边界)
  2. 左闭右开
    • 左区间边界在数组的有效索引范围内,右边界不在(left=0,right=数组长度)
    • 判断条件 left(左边界)<right(右边界)

例题

704. 二分查找 - 力扣(Leetcode)

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

  • 有序数组
  • 数组没有重复元素
//左闭右闭 
public int search(int[] nums, int target) {
    int left=0;
    int right=nums.length-1;
    while(left<=right){
        int n=left+(right-left)/2;
        if(target>nums[n]){
            left=n+1;//当前元素的值不满足,缩小区间
        }else if(target<nums[n]){
            right=n-1;
        }else{
            return n;
        }
    }
    return -1;
}
//左闭右开
public  int search(int[] nums, int target) {
    int left=0;
    int right=nums.length;//不包含右边界
    while(left<right){//left==right不成立
        int n=left+(right-left)/2;
        if(target>nums[n]){
            left=n+1;
        }else if(target<nums[n]){
            right=n;//索引检查始终不包含右边界
        }else{
            return n;
        }
    }
    return -1;
}

35. 搜索插入位置 - 力扣(Leetcode)

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

  • 有序数组
  • 数组没有重复元素
//左闭右闭
public int searchInsert(int[] nums, int target) {
     int left=0;
     int right=nums.length-1;
     while(left<=right){
         int n=left+(right -left)/2;
         if(target>nums[n])
         {
             left=n+1;
         }else if(target<nums[n]){
             right=n-1;
         }else{
             return n;
         }
     }
     return left;//没有查到,当left-1=right时退出循环
 } 
//左闭右开
public int searchInsert(int[] nums, int target) {
    int left=0;
    int right=nums.length;//不包含右边界
    while(left<right){//left==right不成立
        int n=left+(right -left)/2;
        if(target>nums[n])
        {
            left=n+1;
        }else if(target<nums[n]){
            right=n;
        }else{
            return n;
        }
    }
    return left;
} 

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(Leetcode)

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

  • 数组有序
//二分查找对应元素的左右边界
public int[] searchRange(int[] nums, int target) {
     int left=searchRangeLeft(nums,target);
     int right=searchRangeRight(nums,target);
     if(right==-2||left==-2)return new int[]{-1,-1};//target的值比数组最大值大或最小值小
     if(right-left>1)return new int[]{left,right};//target存在在数组中,且因为返回值是边界
   // 元素不存在 
 return new int[]{-1,-1};
 }
 //缩小右边界去找左边界
 public int searchRangeLeft(int[] nums, int target){
     int left=0;
     int right=nums.length-1;
     int leftBro=-2;
     while(left<=right){
         int n=left+(right-left)/2;
         if(target<=nums[n]){
             right=n-1;
             leftBro=right;//当target==nums[n]时更新   
         }else{
             left=n+1;    
         }
     }
return leftBro;
 }
//缩小左边界去找右右边界
 public int searchRangeRight(int[] nums, int target){
     int left=0;
     int right=nums.length-1;
     int rightBro=-2;
     while(left<=right){
         int n=left+(right-left)/2;
         if(target>=nums[n]){
             left=n+1;
             rightBro=left; 
         }else{
             right=n-1;    
         }
     }
return rightBro;
 }
/*****************************************************/
//二分查找要查找的元素,在从查找的元素位置向两侧查找
public int[] searchRange(int[] nums, int target) {
     int left=0;
     int right=nums.length-1;
     while(left<=right){
         int n=left+(right-left)/2;
         if(target>nums[n]){
             left=n+1;
         }else if(target<nums[n]){
             right=n-1;
         }else{//查找到当前元素,开始查找边界
             while(left<=n&&nums[left]!=target){
                 left++;       
             }
             while(right>=n&&nums[right]!=target){
                 right--;
             }
             return new int []{left,right};
         }
     }
 return new int[]{-1,-1};
 }

69. x 的平方根 - 力扣(Leetcode)

给你一个非负整数 x ,计算并返回 x算术平方根

由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5

  • 将整数近似为右边界
public int mySqrt(int x) {
       int i=0; 
       int j=x;
       int ans=-1;
        if(x==0)return 0;
        if(x==1)return 1;//防止n为0的情况
        while(i<=j){
            int n=i+(j-i)/2;
            if(x/n<n){//防止溢出
                j=n-1;
            }else{
                i=n+1;
                ans=n;
          /*只要mid <= x/mid,left左边界就会一直向右移动,ans就会一直更新(变大),直到不在满足mid <= x/mid  的条件为止,ans就会停止更新,永远停在满足mid<=x/mid条件下面的最后一次更新,即满足ans * ans <= mid的最大值*/     
            }
        }
        return ans;
    }

代码随想录 (programmercarl.com)

标签:right,target,nums,int,二分法,数组,left
From: https://www.cnblogs.com/ZD12/p/17458716.html

相关文章

  • 二分法 三元表达式 生成式 匿名函数 内置函数
    目录二分法三元表达式生成式列表生成式字典生成式集合生成式元组生成式(生成器)匿名函数内置函数二分法二分法思路1.二分法的使用前提条件:列表中得数字必须要有序2.将对象整除2分成两部分3.将目标数值与分割后的对象做比较来确定目标数值在哪一部分4.继续重复这两个步骤直至......
  • 算法之二分法、三元表达式、列表生成式、字典生成式(了解)、匿名函数、常见的内置函数
    算法之二分法二分概念二分算法,又称折半查找,即在一个单调有序的集合中查找一个解。每次分为左右两部分,判断解在哪个部分中并调整上下界,直到找到目标元素,每次二分后都将舍弃一半的查找空间。定义and实现:算法就是解决问题的高效办法常见的算法:二分法算法还可以锻炼我们的......
  • 二分法应用——搜索旋转数组,以前一直在纠结a[0],a[-1],a[mid], target三者关系,其实最
    62·搜索旋转排序数组  描述给定一个有序数组,但是数组以某个元素作为支点进行了旋转(比如,0124567可能成为4567012)。给定一个目标值target进行搜索,如果在数组中找到目标值返回数组中的索引位置,否则返回-1。你可以假设数组中不存在重复的元素。背完这套刷题模板,真......
  • 图解LeetCode——886. 可能的二分法(难度:中等)
    一、题目给定一组 n 人(编号为 1,2,...,n), 我们想把每个人分进任意大小的两组。每个人都可能不喜欢其他人,那么他们不应该属于同一组。给定整数n 和数组dislikes ,其中 dislikes[i]=[ai,bi] ,表示不允许将编号为ai 和  bi的人归入同一组。当可以用这种方法将所有人......
  • 二分法
    【二】二分法二分法查找,也称为折半法,是一种在有序数组中查找特定元素的搜索算法。二分法查找的思路如下:(1)首先,从数组的中间元素开始搜索,如果该元素正好是目标元素,则搜索过程结束,否则执行下一步。(2)如果目标元素大于/小于中间元素,则在数组大于/小于中间元素的那一半区域......
  • 二分法
    本质在有序区间内,找到一个分界线,分界线左侧元素均不满足某一个性质,右侧则相反。极端情况下,左边和右边都可能为空。可以按照具体定义将分界线归属为左边或者右边。比如,上面的分界线0左侧都不大于0,右侧都大于0。先决条件区间内元素有序;区间左右端点确定。题目特点求......
  • 1241.二分法求函数零点 | 浮点二分
    1241二分法求函数的零点题目来源信息学奥赛一本通题目描述\(有函数:f(x)=x5−15x4+85x3−225x2+274x−121.已知f(1.5)>0,f(2.4)<0且方程f(x)=0在区间[1.5,2.4]有且只有一个根,请用二分法求出该根。\)输出要求\(该方程在区间[1.5,2.4]中的根。要求四舍五入到小数点后6位。\)......
  • 查找(1.顺序查找、2.二分法查找)
    顺序查找既是for循环,在循环内用if匹配输入的值是否有对等,有即返回对应结果如果for循环下,没有对应的匹配值,要返回提示没找到用如下方法二分法查找1.必须是一个有序的列表2.先找到数组的中间值,拿输入值与其配对3.如果值是小了往左边选中间值,再匹对。反之向右.........
  • 二分法查找子序列
    判断子序列二分思路主要是对t进行预处理,用一个字典index将每个字符出现的索引位置按顺序存储下来intm=s.length(),n=t.length();vector<vector<int>>index(256,vector<int>());//先记下t中每个字符出现的位置for(inti=0;i<n;i++){charc=t[i];......
  • 分巧克力(二分法)
    题目描述儿童节那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。小明一共有N块巧克力,其中第i块是Hi×Wi的方格组成的长方形。为了公平起见,小明需要从这N块巧克力中切出K块巧克力分给小朋友们。切出的巧克力需要满足:形状是正方形,边长是整数;......