麻烦理解稍微修改过的二进制搜索吗?

如何解决麻烦理解稍微修改过的二进制搜索吗?

大家好,我正在尝试解决有关leetcode的问题,称为“搜索插入位置”。继承人的问题: https://leetcode.com/problems/search-insert-position/

问题陈述: 给定一个已排序的数组和一个目标值,如果找到目标,则返回索引。如果不是,则返回按顺序插入索引的位置。

您可以假定数组中没有重复项。

这是一个简单的二进制搜索,我唯一不了解的部分是我必须在最后返回下界才能获得正确的答案。我不明白为什么。如果有人能解释我,我将不胜感激。

doRun(){
   clientConsumer.subscribe(topic);
   while( isRunAllowed() && !reConnect && !isStoppingOrStopped() && !isSuspendingOrSuspended()){
      clientConsumer.poll();
   }
   clientConsumer.unsubscribe(topic) 
} 

解决方法

取决于数组或其分区的大小(偶数或奇数),或者我们设计二进制搜索算法的方式,有时高低之间会有一个索引差异(基于停止条件,这可能会例如lo < hilo <= hi)。返回哪一个并不重要,我们只需要针对这一差异进行调整即可。

在这个问题中,lo将返回预期的结果:

public final class Solution {
    public static final int searchInsert(int[] nums,int target) {
        int lo = 0;
        int hi = nums.length - 1;

        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;

            if (nums[mid] == target) {
                return mid;
            }

            else if (nums[mid] > target) {
                hi = mid - 1;
            }

            else {
                lo = mid + 1;
            }
        }

        return lo;
    }
}
,

在找到中点之前,我们需要初始化起点。每次检查是否找到目标元素时,如果都没有找到目标元素,则更新起点。

,

要了解这一点,您必须注意练习的第二个要求:返回应插入元素的位置。 假设您要在下表中插入数字150。

╔═════╦═════╦═════╦═════╗
║ 100 ║ 200 ║ 300 ║ 400 ║
╠═════╬═════╬═════╬═════╣
║ 0   ║ 1   ║ 2   ║ 3   ║
╚═════╩═════╩═════╩═════╝

完成此操作的方法是创建一个更大的数组,将所有在 之前的元素复制到与它们相同的位置,然后添加数字150,然后复制所有出现的数字之后 150,其指数比以前高。

╔═════╦═════╦═════╦═════╦═════╗
║     ║     ║     ║     ║     ║
╠═════╬═════╬═════╬═════╬═════╣
║ 0   ║ 1   ║ 2   ║ 3   ║ 4   ║
╚═════╩═════╩═════╩═════╩═════╝

╔═════╦═════╦═════╦═════╦═════╗
║ 100 ║     ║     ║     ║     ║
╠═════╬═════╬═════╬═════╬═════╣
║ 0   ║ 1   ║ 2   ║ 3   ║ 4   ║
╚═════╩═════╩═════╩═════╩═════╝

╔═════╦═════╦═════╦═════╦═════╗
║ 100 ║ 150 ║     ║     ║     ║
╠═════╬═════╬═════╬═════╬═════╣
║ 0   ║ 1   ║ 2   ║ 3   ║ 4   ║
╚═════╩═════╩═════╩═════╩═════╝

╔═════╦══════╦═════╦═════╦═════╗
║ 100 ║  150 ║ 200 ║ 300 ║ 400 ║
╠═════╬══════╬═════╬═════╬═════╣
║ 0   ║ 1    ║ 2   ║ 3   ║ 4   ║
╚═════╩══════╩═════╩═════╩═════╝

现在您知道它是如何工作的,您知道插入所需的索引是第一个大于您的target的索引之一。如果所有数字都大于您的target,则表示0(并且所有现有数字都将移到第1到N位),如果所有数字都小于您的target,则为数字N-现有数组的长度(这不是现有数组中的合法索引,但是正如我所解释的,如果您确实想插入数字,则必须创建一个新数组。但这不属于此部分)锻炼)。

现在,为什么start是正确的索引?

当您要查找的元素不在数组中时,middle元素将永远不匹配。因此,您将startlast彼此越来越靠近。在最后一次迭代中,您最终使它们指向同一元素。在这种情况下,start == middle == last

现在,他们都指向的元素大于target或小于target

少于target

else if(target>nums[middle]){
    start=middle+1;
}

在此语句之后,我们有lastmiddle仍指向nums[middle]数字,该数字比target小。但是start将指向其后的一个位置。 nums[middle]之后的数字是大于target的第一个数字。如果您不明白为什么,请考虑我们如何从上一次迭代中解决这种情况。索引last始终指向大于target的数字,直到将其“移到”一个位置“太多”为止。

大于target

else
    last=middle-1;

在这种情况下,我们刚刚将last移动到了startmiddle以下的位置-我们知道它比* target . So... the current position is *greater*,the position where 最后一个{ 1}},那么当前位置( point is *lessstart仍指向)是大于middle的第一个数字。

在两种情况下,target都将指向正确的位置-大于start的第一个元素的位置。

让我们在示例数组中查看它。当我们尝试插入150时,会发生什么?

  1. target为0(100),start为3(400)。根据整数除法,lastmiddle,它是1(200)。 200> 150,因此我们进入(0+3)/2,并将else设置为last,它是0(100)。
  2. middle - 1最后start is still 0 (100),but 中间is now also 0 (100). They are equal,and,否则is now also 0 (100). 100 < 150,so we get to the开始`现在设置为1(200)。

因此,一旦,and 移至大于start的数字,我们便停止了,实际上插入点应该为1!

让我们对350做同样的事情

  1. target为0(100),start为3(400)。根据整数除法,lastmiddle,它是1(200)。 200 (0+3)/2,而else if现在是start,所以2(300)。
  2. middle +1是2(300),start是3(400)。 lastmiddle,即2(300)。 300 (2+3)/2,而else if现在是start,所以3(400)。
  3. middle + 1是3(400),start是3(400),中间是相同的。 400> 350,因此我们进入lastelse将移至2(300)。

现在last大于start,我们再次看到last实际上是大于350的第一个元素。确实,正确的插入点是350会是3。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-