Java 二进制搜索中的最大键比较(1&èx2B;log(n))而不是log(n)是如何进行的?

Java 二进制搜索中的最大键比较(1&èx2B;log(n))而不是log(n)是如何进行的?,java,arrays,algorithm,binary-search,logarithm,Java,Arrays,Algorithm,Binary Search,Logarithm,我正在对BS进行更全面的解释。它有一个介词,在二进制搜索中最大键比较数是(1+log(n))。我试图形成一种直觉,知道这是怎么可能的。我知道BS的破坏时间是(log(n))。我还推测,当我们搜索数组中不存在的元素时,场景中会出现更糟糕的时间/最大键查找。但是每次我在一个假设的数组上做一个BS,我得到的结果是(log(n))比较/步数永远不会超过这个。这是用来构成这个介词的代码 public static int binarySearch(int[] a, int key){ int l

我正在对BS进行更全面的解释。它有一个介词,在二进制搜索中最大键比较数是(1+log(n))。我试图形成一种直觉,知道这是怎么可能的。我知道BS的破坏时间是(log(n))。我还推测,当我们搜索数组中不存在的元素时,场景中会出现更糟糕的时间/最大键查找。但是每次我在一个假设的数组上做一个BS,我得到的结果是(log(n))比较/步数永远不会超过这个。这是用来构成这个介词的代码

public static int binarySearch(int[] a, int key){
     int lo = 0, hi = a.length-1;
     while (lo <= hi){
         int mid = lo + (hi - lo) / 2;

         if (key < a[mid]) 
            hi = mid - 1;
         else if (key > a[mid]) 
            lo = mid + 1;
         else 
            return mid;
     }
     return -1;
 }
公共静态int二进制搜索(int[]a,int键){
int-lo=0,hi=a.length-1;
而(低a[中])
lo=中间+1;
其他的
中途返回;
}
返回-1;
}

可能我的猜测是错误的,或者我遗漏了一些要点。如果您能解释最大可能密钥比较是(1+log(n)),那将非常感谢。

不要忘记,即使只有1个元素,您也必须猜测它,因为目标可能不在数组中。所以我们需要在最后一个猜测中加上+1,当我们到达最后剩下的元素时

如果您考虑一下何时
n=1
,可能会更清楚。我们仍然需要1个猜测,但是
log_2(1)=0
。因此,我们需要添加一个
+1
来修正公式

n
不是2的幂时,我们可以上升到下一个更高的幂2。对于长度为1000的数组,次高的2次方为1024,即10。因此,对于1000个元素的数组,二进制搜索最多需要11(10+1)次猜测

为什么?


在最坏的情况下,二进制搜索将需要10个步骤来分隔剩余的数字,最后一个步骤是检查剩下的唯一一个数字是否是您想要的,或者它不在数组中。

不要忘记,即使只有1个元素,您也必须猜测它,因为目标可能不在数组中。所以我们需要在最后一个猜测中加上+1,当我们到达最后剩下的元素时

如果您考虑一下何时
n=1
,可能会更清楚。我们仍然需要1个猜测,但是
log_2(1)=0
。因此,我们需要添加一个
+1
来修正公式

n
不是2的幂时,我们可以上升到下一个更高的幂2。对于长度为1000的数组,次高的2次方为1024,即10。因此,对于1000个元素的数组,二进制搜索最多需要11(10+1)次猜测

为什么?


在最坏的情况下,二进制搜索需要10个步骤来分隔剩余的数字,最后一个步骤是检查剩下的唯一一个数字是否是您想要的,或者它不在数组中。

想象一个大小为8的数组

l=0, h = 7, mid =  0 + (7-0)/2 = 3   go right
l=4, h = 7, mid =  4 + (7-4)/2 = 5   go right
l=6, h = 7, mid =  6 + (7-6)/2 = 6   go right
l=7, h = 7, mid =  7 + (7-7)/2 = 7   go left  
l=7, h=6 ====> terminates
总比较=1+日志8=4

EDIT1:想象一下这个阵列,用笔和纸画出上面的步骤。搜索值13

index:      0  1  2  3  4  5  6   7   
            ------------------------------
element:    1  3  5  6  7  9  11  15  

想象一个大小为8的数组

l=0, h = 7, mid =  0 + (7-0)/2 = 3   go right
l=4, h = 7, mid =  4 + (7-4)/2 = 5   go right
l=6, h = 7, mid =  6 + (7-6)/2 = 6   go right
l=7, h = 7, mid =  7 + (7-7)/2 = 7   go left  
l=7, h=6 ====> terminates
总比较=1+日志8=4

EDIT1:想象一下这个阵列,用笔和纸画出上面的步骤。搜索值13

index:      0  1  2  3  4  5  6   7   
            ------------------------------
element:    1  3  5  6  7  9  11  15  

这里有一种不同的方式来思考你在做什么。与其将二进制搜索视为对数组元素的搜索,不如将二进制搜索视为对数组元素之间的分隔符的搜索。具体地说,想象一下对数组进行如下编号:

   +-----+-----+-----+-----+-----+
   |  0  |  1  |  2  | ... | n-1 |
   +-----+-----+-----+-----+-----+
现在,为分离器编号:

   +-----+-----+-----+-----+-----+
   |  0  |  1  |  2  | ... | n-1 |
   +-----+-----+-----+-----+-----+
   0     1     2     3 .. n-1    n
请注意,共有n+1个分隔符,每个元素前一个,最后一个元素后一个

无论何时进行二进制搜索,都要探测中间分隔符的索引(你知道为什么吗?),并扔掉一半分隔符。你可以在你只剩下一个元素之前。这意味着所需的探头数量将减少⌈log2(n+1)⌉, 碰巧是这样的

log2 n<⌈log2(n+1)⌉ ≤ log2n+1

因此,“1+logn”位最终产生于“扔掉一半分离器”而非其他来源


希望这有帮助

这里有一种不同的方式来思考你在做什么。与其将二进制搜索视为对数组元素的搜索,不如将二进制搜索视为对数组元素之间的分隔符的搜索。具体地说,想象一下对数组进行如下编号:

   +-----+-----+-----+-----+-----+
   |  0  |  1  |  2  | ... | n-1 |
   +-----+-----+-----+-----+-----+
现在,为分离器编号:

   +-----+-----+-----+-----+-----+
   |  0  |  1  |  2  | ... | n-1 |
   +-----+-----+-----+-----+-----+
   0     1     2     3 .. n-1    n
请注意,共有n+1个分隔符,每个元素前一个,最后一个元素后一个

无论何时进行二进制搜索,都要探测中间分隔符的索引(你知道为什么吗?),并扔掉一半分隔符。你可以在你只剩下一个元素之前。这意味着所需的探头数量将减少⌈log2(n+1)⌉, 碰巧是这样的

log2 n<⌈log2(n+1)⌉ ≤ log2n+1

因此,“1+logn”位最终产生于“扔掉一半分离器”而非其他来源


希望这有帮助

你能不能通过选取一个大小为8的数组并决定要搜索的元素来详细说明一下呢?考虑一下大小为8的数组。想象一下,在搜索一个元素时,必须选择上面的中间索引。最好的理解方法是用笔和纸:-)你能用一个8号数组来详细说明一下,然后决定你要搜索的元素吗。想象一下,在搜索一个元素时,必须选择上面的中间索引。最好的理解方法是用笔和纸:-)