【问题标题】:How do I return an index of where a number should go if it isn't found in a Binary Search in JAVA如果在 JAVA 的二进制搜索中找不到数字,我如何返回该数字应该去哪里的索引
【发布时间】:2015-03-26 16:58:52
【问题描述】:

所以我有一个二进制搜索代码,可以找到应该放置数字以保持排序顺序的位置。到目前为止,我已经在这个问题上待了一个半多小时,试图弄清楚这一点,这样我就可以继续推进了。

如果在数组中没有找到该值,但找到了应该放置的位置,我会在方法末尾返回什么值?基本上一个值表示该数字所属的索引在中间值的 +/- 1 范围内。

这里是二分搜索,我不想改变它,而只是寻找返回_____所在位置的变量。

private static int bsearch( int[] arr, int count, int key )
{
    if (count==0) return -1;
    int lo = 0, hi = count - 1, mid;
    while(hi >= lo)
    {
          mid = (lo + hi) / 2;
          if(arr[mid] == key) return mid;
          if ( key < arr[mid] ) hi = mid-1;
          else lo = mid+1;
    }
    return _____;        
}   

【问题讨论】:

  • 这样想:如果搜索值高于你找到的最后一个mid,它应该是mid+1,对吧?如果它的下限不应该是中间-1?

标签: java arrays binary-search


【解决方案1】:

大多数方法返回放置元素的索引的按位否定,即~idx

二分搜索假设lo 之前的所有元素都小于keyhi 的类似元素。

如果hi &lt; lo,则表示hi 设置为mid-1,而mid 等于lo(因为hilo 最多相差一个)或类似于@987654333 @。因此,必须放置元素的位置是lo。于是返回:

return ~lo;

因此该算法的优化版本是:

private static int bsearch( int[] arr, int count, int key) {
    if (count==0) return -1;
    int lo = 0, hi = count - 1, mid = hi>>1;
    while(hi >= lo) {
          mid = (lo + hi) >> 1;
          if ( key < arr[mid] ) hi = mid-1;
          else if ( key > arr[mid] ) lo = mid+1;
          else return mid;
    }
    return ~lo;
}

作为测试用例:

for(int i = 0; i <= 22; i++) {
    int r = bsearch(new int[] {2,3,7,9,11,15,21},7,i);
    System.out.println(""+i+" -> "+r+" "+(~r));
}

给予:

0 -> -1 0
1 -> -1 0
2 -> 0 -1
3 -> 1 -2
4 -> -3 2
5 -> -3 2
6 -> -3 2
7 -> 2 -3
8 -> -4 3
9 -> 3 -4
10 -> -5 4
11 -> 4 -5
12 -> -6 5
13 -> -6 5
14 -> -6 5
15 -> 5 -6
16 -> -7 6
17 -> -7 6
18 -> -7 6
19 -> -7 6
20 -> -7 6
21 -> 6 -7
22 -> -8 7

x -&gt; i ji 结果和j 按位负数(用作插入索引,以防i 为负数)。

online JDoodle demo.

【讨论】:

  • 结果为@​​987654343@。所以你可以先检查它是否小于0,如果是,再次使用按位否定计算插入位置是0
【解决方案2】:

Arrays.binarySearch

return -low - 1;

一个负数,最多 -1。因为mid(插入点)的范围是0。

退货

搜索键的索引,如果它包含在数组中;除此以外, (-(插入点) - 1)。插入点定义为点 键将被插入到数组中的位置: 第一个大于键的元素,或者 a.length 如果所有元素都在 数组小于指定的键。请注意,这保证了 当且仅当找到键时,返回值将 >= 0。

【讨论】:

  • 这样我得到一个错误,告诉我 mid 从未被初始化,这是有道理的,因为 mid 只是在 while 循环中被初始化,我将如何处理这个问题?
  • @NoivernEvo:您必须在 while 循环之前初始化 mid。例如(lo+hi)&gt;&gt;1.
  • 是的,您必须将 mid 初始化为 0。特别是对于零长度数组的情况。你也可以使用lo
  • @JoopEggen:带有{2,3,7,9,11,15,21} 的测试用例给出了22 的错误结果。人们期望-8 (-7-1)。但它给出了-7。不应该使用low吗?
  • 当然。我通常以不同的方式编写循环。已更正。
【解决方案3】:

实际代码是return -1。但我对你的描述感到困惑。什么是“如果在数组中没有找到值,但找到了它应该放置的位置?”意义? 该值要么在数组中找到,要么不在。在while之前没有找到,表示不在数组中,应该return -1

【讨论】:

  • 二分查找通常返回索引的取反结果。
  • 提问的朋友用mid写错了代码,我忽略了他的代码。但是在二分查找中return -1是常识,ohhhh,如果方法没有找到数组中的值,你想得到什么?
  • 好吧Java的binary search没有使用这个常识,而是使用了插入索引。仅当列表未排序时(例如在字符串中搜索 char 的情况),才返回 -1。
猜你喜欢
  • 2019-06-24
  • 2021-02-20
  • 1970-01-01
  • 1970-01-01
  • 2012-01-24
  • 1970-01-01
  • 2019-10-18
  • 2022-01-22
  • 1970-01-01
相关资源
最近更新 更多