Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在二进制搜索中找到数组的最后一个元素_Java_Algorithm_Binary Search - Fatal编程技术网

Java 如何在二进制搜索中找到数组的最后一个元素

Java 如何在二进制搜索中找到数组的最后一个元素,java,algorithm,binary-search,Java,Algorithm,Binary Search,在二进制搜索算法中,上限元素是数组.length-1,那么如何找到数组的最后一个元素呢 如果长度为8的数组元素的下界和上界分别为6和7,则我的中间元素为: mid=(6+7)/2,即java中的6您可以每次四舍五入 (6+7)/2.0==6.5 把它四舍五入,你会得到7 或者你可以简单地在中点加一个 中期=(6+7)/2+1 另一种方法是在下面的递归中将起点或终点更改为+1或-1。这是维基百科关于这个主题的文章在一些实现中所展示的 最小值=中间值+1 或 max=mid-1当下限和上限在一个范围

在二进制搜索算法中,上限元素是数组.length-1,那么如何找到数组的最后一个元素呢

如果长度为8的数组元素的下界和上界分别为6和7,则我的中间元素为:


mid=(6+7)/2,即java中的6

您可以每次四舍五入

(6+7)/2.0==6.5

把它四舍五入,你会得到7

或者你可以简单地在中点加一个

中期=(6+7)/2+1

另一种方法是在下面的递归中将起点或终点更改为+1或-1。这是维基百科关于这个主题的文章在一些实现中所展示的

最小值=中间值+1


max=mid-1

当下限和上限在一个范围内时,请同时选中两者。

最简单的方法是使用半开放范围。这样,虽然下限直接指向第一项,但上限指向数组中最后一个有效项之后的一步。但是,在搜索过程中,您将范围视为包含范围-超出范围上限是有效的“未找到匹配项”结果

在每次迭代开始时,您都有

lower <= target <= upper
注意

编辑以纠正一些错误,这些错误使得这个问题如同它要修复的一样无限循环

诀窍是确保在每次按键测试后对分的子范围完全符合需要,并且总是至少比原来的全范围小一个-通过过度自信和糟糕的记忆,这正是我设法出错的原因。以上内容基于大量使用的库中的实际工作代码(在多路树库中的节点中搜索),因此,如果它是错误的,我就会遇到大问题;-)

注意


再次编辑以改进措辞并简化子范围边界描述(注意,虽然范围是半开放的,但它们被视为包含性的)。

这实际上归结为使用正确选择的中点进行比较。例如(没有变量类型声明)

就这么简单

编辑:还有一件事,我查看了用于此目的的代码,并意识到您还必须更改对binsearch的调用,以在最右边的元素上结束。我将发布这方面的完整代码(这是我首先应该做的)。这里是一个二进制搜索,查找与val相等的最右边的元素

binsearch(a,val,left,right){
    if(left==right) return left;
    mid = (left+right+1)/2;
    if(a[mid] > val)
        return binsearch(a,val,left,mid-1);
    else
        return binsearch(a,val,mid,right);
}

众所周知,二进制搜索很难精确地得到正确的结果。对各种问题和边缘案例进行了非常透彻的分析,并正确实施,,一本每个程序员都应该至少读过一次的书。

不是最后一个元素索引是
array。length-1
在我看来,这是非常糟糕的措辞,所以希望我的答案能回答正确的问题。@Justin-同意。我假设黄昏在寻找钥匙时得到了一个无限循环。如果发生这种情况,则表明平分的子范围有一个项目重叠,因此确定哪个子范围测试可以(重复)选择错误的子范围。数组中的最后一项有点像是在转移视线——还有其他失败案例。看起来你的猜测是一样的,但这与问题的措辞有点不同。@Joel-你完全不恰当地用[multiway tree]重新标记了一堆问题。请停止这样做;每次我都被迫手动删除标签。你的一些编辑是合法的,但有这样一个问题,我看不出你怎么认为标签是合适的。向下投票人:每个人都受益于对不正确或不清楚的解释。我没有向下投票,但摆弄舍入规则不会给你一个有效的二进制搜索。如果您使用的不是半开放范围,那么您会遇到复杂的编码问题,这会使代码变得更慢、更脆弱。不同的舍入规则可以改变失败案例,但不能解决根本问题。循环中的额外检查可以解决这个问题,不管你如何循环,但需要它只能证明你还没有尝试过二进制搜索。半开放范围,每个循环一次完成检查和一次键测试,做二进制搜索自然会做的事情,然后在循环外添加额外的检查。我发现这很有用。如果您想了解为什么需要取整,请以数组大小为4[1,2,3,4]为例,我们需要找到4。第一次运行后,通过mid=2和high=3。如果我们简单地取平均值,我们会得到(2+3)/2=2。所以为了解决这个问题,我们需要加1(四舍五入)以避免丢失最后一个值。这看起来是正确的,但我不喜欢+1。我的版本意味着替换“您可能会在一半的时间内出现相同的值,最后一个值为niot。不过,如果数组中有所有唯一的值,这是可行的。如果要查找最右边的元素,这可能是真的。我意识到我没有给出所有需要进行的更改,以使其找到与val相等的最右边元素,所以我只发布了第二个binsearch代码。我撤回了关于+1的评论-正如Justin指出的,我的版本是无限循环-我真的应该在发布前仔细检查,因为我并不是每天都写二进制搜索!我用Python测试了这段代码,它在最后两个元素上一直循环。我甚至尝试了它,一个几乎正确的实现。。。()@LukeUsherwood:哎哟-这只是为了证明总还有一只虫子!
if array[mid] >  k :  lower <= target <= mid
if array[mid] <= k :  mid+1 <= target <= upper
int find_first_ge (int key)
{
  int lower = 0;
  int upper = array.length;

  while (upper > lower)
  {
    int mid = (lower + upper) / 2;

    if (array [mid] >= key)  //  for find_first_gt, use ">" here
    {
      upper = mid;
    }
    else
    {
      lower = mid + 1;
    }
  }

  return lower;
}
binsearch(a,val,left,right){
    if(left==right) return left;
    mid = (left+right)/2;
    if(a[mid] < val)
        return binsearch(a,val,mid+1,right);
    else
        return binsearch(a,val,left,mid);
}
mid = (left+right+1)/2;
binsearch(a,val,left,right){
    if(left==right) return left;
    mid = (left+right+1)/2;
    if(a[mid] > val)
        return binsearch(a,val,left,mid-1);
    else
        return binsearch(a,val,mid,right);
}