首页 > 其他分享 >二分法查找

二分法查找

时间:2025-01-08 20:45:55浏览次数:1  
标签:right target nums int 二分法 middle 查找 left

二分法查找算法应用的条件:

  • 数组按照顺序排列【基础】;
  • 数组中没有重复的元素【否则返回值元素的下标不唯一】;

二分法查找主要难点在于边界条件的确定,常见的区间的定义一般有两种:左闭右闭,即 [left, right],或者左闭右开,即 [left, right);

第一种:左闭右闭,即 [left, right],代码如下:

class Solution {
    public int search(int[] nums, int target) {
        int res = -1;
        int right = nums.length -1;
        int left = 0;
        while (left <= right) {            //重点在于循环条件的确定;
            int middle = left + ((right - left) >> 1);
            if (nums[middle] > target) {
                right = middle -1;
            }
            else if (nums[middle] < target) {
                left = middle +1;
            }
            else {
                res = middle;
                break;
            }
        }
        return res;
    }
}

第二种:左闭右开,即 [left, right),代码如下:

class Solution {
    public int search(int[] nums, int target) {
        int res = -1;
        int right = nums.length;
        int left = 0;
        while (left < right) {				//循环条件的确定
            int middle = left + ((right - left) >> 1);
            if (nums[middle] > target) {
                right = middle;
            }
            else if (nums[middle] < target) {
                left = middle +1;
            }
            else {
                res = middle;
                break;
            }
        }
        return res;
    }
}

两种方法的区别:

  • 左闭右闭,即 [left, right],
    • 当left = right时,仍然要进入循环;
    • 当没有找到 target 值时,循环体结束后,left - right = 1
  • 左闭右开,即 [left, right),
    • 当left = right时,跳出循环;
    • 当没有找到 target 值时,循环体结束后,right = left

此外,涉及到边界条件问题:

  • 例如:在排序数组中查找元素的范围【数组非严格单调,存在重复元素】,此时,需要确定范围的左右区间;

  • 区间的确定:

    \[左区间:nums[pos−1]<target≤nums[pos]\\ 右区间:nums[pos−1]≤target<nums[pos] \]

  • 当为左闭右闭,即 [left, right]时:

    public int getRight(int[] nums, int target) {
            int res = -1;
            int right = nums.length - 1;
            int left = 0;
            while (right >= left) {
                int middle = left + ((right - left) >> 1);
                if (nums[middle] > target) {
                    right = middle -1;
                }
                else {
                    left = middle + 1;
                }
            }
            res = left;
            }
            return res;
        }
    public int getLeft(int[] nums, int target) {
            int res = -1;
            int right = nums.length - 1;
            int left = 0;
            while (right >= left) {
                int middle = left + ((right - left) >> 1);
                if (nums[middle] < target) {
                    left = middle + 1;
                }
                else {
                    right = middle -1;
                }
            }
            res = right;
            return res;
        }
    
    • 循环体结束后,left - right = 1

    • 当数组不存在对应target元素时,左右区间产生的left,right完全一样;

    • 当数组中存在一个元素时

      • left - right = 1

      • \(right_{左区间}\) = \(left_{右区间}\)

      • 由上面两个公式,可得:

        \(right_{右区间} - left_{左区间}=2\)

    • 当数组中存在多个元素时,同理:

      • \(right_{右区间} - left_{左区间}=2 + 元素个数\)
    • 统一范围:[\(left_{左区间} +1, right_{右区间} -1\)],

  • 当为左闭右开,即 [left, right)时,代码如下:

        public int getRight(int[] nums, int target) {
            int res = -1;
            int right = nums.length;
            int left = 0;
            while (right > left) {
                int middle = left + ((right - left) >> 1);
                if (nums[middle] > target) {
                    right = middle;
                }
                else {
                    left = middle + 1;
                }
            }
            res = left;
            return res;
        }
        public int getLeft(int[] nums, int target) {
            int res = -1;
            int right = nums.length;
            int left = 0;
            while (right > left) {
                int middle = left + ((right - left) >> 1);
                if (nums[middle] < target) {
                    left = middle + 1;
                }
                else {
                    right = middle;
                }
            }
            res = right;
            return res;
        }
    
    • 循环体结束后,left = right,并且最后一步骤基本都是 left = left + 1
    • 当数组不存在对应target元素时,
      • target元素在数组的范围内,但不存在时,left = right=靠近较大值的索引,例如:nums = [0, 0, 2, 2],target = 1, \(left = right = 2_{index}\)
      • target元素不在数组的范围内,且不存在时,left = right = 0 or nums.length
    • 当数组中存在一个元素时:
      • 左区间:$left_{右区间} = right_{右区间} $ = 元素索引;
      • 右区间: $left_{右区间} = right_{右区间} $ = 元素索引 + 1;
      • 因为当left和right相邻的时候,middle取的是 left的值作为索引,而左闭右开,则还会执行一次;
    • 当数组中存在多个元素时,
      • 左区间:$left_{右区间} = right_{右区间} $ = 元素索引;
      • 右区间: $left_{右区间} = right_{右区间} $ = 元素索引 + 元素个数;
    • 统一范围:[$left_{左区间} , right_{右区间} -1 $];

标签:right,target,nums,int,二分法,middle,查找,left
From: https://www.cnblogs.com/xiaoxianglu/p/18660507

相关文章

  • 代码随想录算法训练营第1天 | 数组理论基础,704. 二分查找,27. 移除元素,977.有序数组的
    1.刷题部分1.1数组基础理论原文链接:代码随想录1.1.1题目内容知识性讲解,点击链接查看原文。1.1.2初见想法是一些很基本的知识,看看有么有什么生疏的。1.1.3看录后想法原来有的语言的二维数组元素地址是可以行与行之间不连续的。1.1.4遇到的困难暂未遇到困难。1.......
  • Windows bat批处理用for遍历、循环、查找的变量不能在for外用
    前言全局说明Windowsbat批处理用for遍历、循环、查找的变量不能在for外用Windowsbat不像Linuxshell有很完善的语法,bat中除了判断,很多查询或要遍历的东西都要用for完成。一、说明1.1环境:Windows二、for循环变量下面的写法,for循环外是获取不到file,因......
  • 二分查找疑难点-区间问题
        大家在写二分查找时,对while()循环中的left<right还是left<=right以及right=mid还是right=mid-1经常会搞混,下面理清这里面的逻辑。   首先说明一下二分查找的使用条件,1.元素需要有序,这样才能二分,2.无重复元素,因为重复元素会导致查找成功返回的下标......
  • [数据结构学习笔记8] 二叉查找树(Binary Search Trees)
    二叉查找树,它是一类特殊的二叉树,除了基本的二叉树规则外,还要满足:1.左边的子节点要小于父节点值2.右边的子节点要大于父节点值 图示:添加节点:        42       |   |      24  99      |    | ......
  • Opencv查找、绘制轮廓、圆形矩形轮廓和近似轮廓
    查找、绘制轮廓、圆形矩形轮廓和近似轮廓目录查找、绘制轮廓、圆形矩形轮廓和近似轮廓1轮廓查找和绘制1.1轮廓查找1.1.1函数和参数1.1.2返回值1.2轮廓绘制1.2.1函数和参数1.3步骤1.4实际测试绘制轮廓2绘制近似轮廓2.1函数和参数2.2查找特定轮廓2.3近似轮......
  • 算法浅谈:插入-标记-查找
    前言lxl的课属实让我受益匪浅,这篇博客就来谈一谈他自创的算法:插入-标记-查找算法概述这是一个离线算法,用到了扫描线思想和数据结构,它可以秒掉这样一类问题:给定\(n\)个映射\(f_i(x)\;(i\in[1,n])\)和\(m\)个询问每个询问形如给定\(x,l,r\)求\(f_r(f_{r-1}(\dots......
  • 学习随想:高维AI数据的训练和推理与一维数据的排序和查找
    以下是看AttentionIsAllYouNeed这篇文章的一点随想。说实话,我没看懂transformer是咋回事,但突然一个类比念头,让我感觉有点概念了,虽然所有的类比都是不完备的。学习随想记录如下,仅供查考:物理世界高维AI数据一维数据物理对象n维矩阵向量,Word2vec一维数组观察与实验数据......
  • 【C语言】数组——二分查找
    题1704.二分查找【简单】intsearch(int*nums,intnumsSize,inttarget){intleft=0,right=numsSize-1;intmid=(left+right)/2;intresult=-1;while(left<=right){if(nums[mid]==target){r......
  • 二分查找 - 相关基础算法总结
    问题1:寻找target位置,没有返回-1问题2:从右往左,寻找<target的第一个位置问题3:从左往右,寻找>target的第一个位置问题4:从右往左,寻找<=target的第一个位置问题5:从左往右,寻找>=target的第一个位置以上问题是求很多解力扣算法题的基础,需要好好的掌握: 问题1:寻找......
  • 【优选算法】Binary-Blade:二分查找的算法刃(下)
    文章目录1.山脉数组的峰顶索引2.寻找峰值3.寻找旋转排序数组中的最小值4.点名希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力!本篇接上一篇二分查找,主要通过部分题目熟悉二分查找的进阶使用,重点强调二段性,找到两个区间不同的地方在哪,多画图划分界限......