如何解决麻烦理解稍微修改过的二进制搜索吗?
大家好,我正在尝试解决有关leetcode的问题,称为“搜索插入位置”。继承人的问题: https://leetcode.com/problems/search-insert-position/
问题陈述: 给定一个已排序的数组和一个目标值,如果找到目标,则返回索引。如果不是,则返回按顺序插入索引的位置。
您可以假定数组中没有重复项。
这是一个简单的二进制搜索,我唯一不了解的部分是我必须在最后返回下界才能获得正确的答案。我不明白为什么。如果有人能解释我,我将不胜感激。
doRun(){
clientConsumer.subscribe(topic);
while( isRunAllowed() && !reConnect && !isStoppingOrStopped() && !isSuspendingOrSuspended()){
clientConsumer.poll();
}
clientConsumer.unsubscribe(topic)
}
解决方法
取决于数组或其分区的大小(偶数或奇数),或者我们设计二进制搜索算法的方式,有时高低之间会有一个索引差异(基于停止条件,这可能会例如lo < hi
或lo <= 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
元素将永远不匹配。因此,您将start
和last
彼此越来越靠近。在最后一次迭代中,您最终使它们指向同一元素。在这种情况下,start == middle == last
。
现在,他们都指向的元素大于target
或小于target
。
少于target
else if(target>nums[middle]){
start=middle+1;
}
在此语句之后,我们有last
和middle
仍指向nums[middle]
数字,该数字比target
小。但是start
将指向其后的一个位置。 nums[middle]
之后的数字是大于target
的第一个数字。如果您不明白为什么,请考虑我们如何从上一次迭代中解决这种情况。索引last
始终指向大于target
的数字,直到将其“移到”一个位置“太多”为止。
大于target
else
last=middle-1;
在这种情况下,我们刚刚将last
移动到了start
和middle
以下的位置-我们知道它比* target . So... the current position is *greater*,the position where
最后一个{ 1}},那么当前位置( point is *less
和start
仍指向)是大于middle
的第一个数字。
在两种情况下,target
都将指向正确的位置-大于start
的第一个元素的位置。
让我们在示例数组中查看它。当我们尝试插入150时,会发生什么?
-
target
为0(100),start
为3(400)。根据整数除法,last
是middle
,它是1(200)。 200> 150,因此我们进入(0+3)/2
,并将else
设置为last
,它是0(100)。 -
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做同样的事情
-
target
为0(100),start
为3(400)。根据整数除法,last
是middle
,它是1(200)。 200 (0+3)/2,而else if
现在是start
,所以2(300)。 -
middle +1
是2(300),start
是3(400)。last
是middle
,即2(300)。 300 (2+3)/2,而else if
现在是start
,所以3(400)。 -
middle + 1
是3(400),start
是3(400),中间是相同的。 400> 350,因此我们进入last
,else
将移至2(300)。
现在last
大于start
,我们再次看到last
实际上是大于350的第一个元素。确实,正确的插入点是350会是3。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。