二进制搜索的步骤数


12

给定正整数输入,输出通过从1开始的二进制搜索找到输入所需的步数。

我们正在模拟对作为输入的整数的二进制搜索,其中模拟的搜索者可以反复猜测一个整数,并告知该整数是太高,太低还是正确。查找整数的策略如下:

  • 令n为我们要查找的输入整数。

  • 从1的猜测开始。(对于每个猜测,请增加步数(无论是否正确),如果猜测正确,则立即停止并输出总步数。)

  • 反复将猜测加倍,直到猜测大于n(目标数字)。(或者,如果它是正确的,但是上面已经提到的我们的正确猜测规则已经涵盖了这一点。)

  • 现在,设置大于n的2的幂的上限(即,刚猜到的数字),并在其正下方设置2的幂的下限。

  • 反复猜测上限和下限的平均值(四舍五入)。如果它太高,则将其设置为上限。如果它太低,则将其设置为下限。此过程可确保最终导致正确的猜测。

这是一个示例,输入n = 21:

1 -> 2 -> 4 -> 8 -> 16 -> 32 -> 24 -> 20 -> 22 -> 21
\__________________________/
   repeated doubling      \________________________/
                             repeated averaging

由于这是,因此以字节为单位的最短代码将获胜。

以下是从n = 1到n = 100的所有输出:

1
2
4
3
6
5
6
4
8
7
8
6
8
7
8
5
10
9
10
8
10
9
10
7
10
9
10
8
10
9
10
6
12
11
12
10
12
11
12
9
12
11
12
10
12
11
12
8
12
11
12
10
12
11
12
9
12
11
12
10
12
11
12
7
14
13
14
12
14
13
14
11
14
13
14
12
14
13
14
10
14
13
14
12
14
13
14
11
14
13
14
12
14
13
14
9
14
13
14
12

这是一些更大的测试用例:

1234 -> 21
1337 -> 22
3808 -> 19
12345 -> 28
32768 -> 16
32769 -> 32
50000 -> 28

Answers:


10

Japt,13个12字节

哦,天哪,我一次击败了果冻和佩斯:D

¢a1 ªJ +1+¢l

在线测试!

这是我使用的策略:让x为输入整数,让bx的二进制表示形式。正确的输出是1 +的长度b + a的最后一个索引1b,减1如果此指数是0。


2
我告诉过你丹尼斯会赢。
lirtosiast'2

7

果冻,18 15 10 9字节

B>WU;BḄBL

在线尝试!或验证小测试用例大测试用例

背景

n为一个正整数,m2的最小幂,大于或等于n

  • 对于m的二进制表示形式中的每个数字,加倍阶段都需要执行一个步骤。

  • n的二进制表示形式,除去第一个,最高有效数字(始终为1)和所有尾随零。的平均相位会针对每个剩余的位数的一个步骤。

为了避免计算,我们观察到的是,如果N <M ,的二进制数字数Ñ正好是一个小于中的二进制数位的数量

如果我们将n的第一个二进制数字替换为0,则将结果取反,追加原始二进制数字并删除所有前导零,那么将发生以下情况:

  • 如果Ñ是一个功率2所有的第一(经修饰)的位数的一半得到去除,只留下的原始二进制表示的位数N = M

  • 如果ñ没有的功率2,上半年对应于最显著位并数字没有得到拆除,补偿的事实,ñ有一个二进制数字小于

怎么运行的

B>WU;BḄBL  Main link. Input: n

B          Compute the binary representation of n.
 >W        Compare it with [n].
           n is positive, so it is not less than the first binary digit and the
           comparison yields zero. When comparing lists of different length, the
           elements in the longer list that do not have a pair remain untouched.
           Therefore, this will just zero out the first binary digit.
   U       Reverse the modified binary representation.
    ;B     Concatenate it with the unmodified binary representation of n.
      ḄB   Convert from binary to integer, and back to binary.
           This removes leading zeroes.
        L  Get the length of the resulting array.

’B;Bt0L(7个字节)在最新版本的Jelly中工作,使用与我的Julia回答中相同的方法。
丹尼斯

4

ES6,38个字节

x=>33-(g=Math.clz32)(x-1)+g(x&-x)-g(x)

正如其他答案所暗示的那样,您可以从第一位和最后一位的位置计算步数。

倍增阶段的步数为n=33-Math.clz32(x-1)。我们想要2ⁿ≥x,但n=33-Math.clz32(x)给我们2ⁿ> x,所以我们从x减去1进行补偿。

平均阶段中的步骤数比较容易,很简单n=Math.clz32(x&-x)-Math.clz32(x)x&-x是一个方便的表达式,其计算结果的最低位x(为2的幂)。


x&-x工作如何?我本来以为它将求出x的绝对值。
ETHproductions 2016年

2
在此页面上找到了一个很好的解释(请参阅第7点攻击)。
ETHproductions 2016年

2

珀斯,15 13字节

h-y.ElQ/PPyQ2

我发现要计算的数字是 1 + 2*ceil(log_2(x)) - [number of 2s in x's prime factorization, minus 1 if x is a power of 2 greater than 1].

在这里尝试。


2

朱莉娅,37 35字节

n->endof(strip(bin(n-1)bin(n),'0'))

感谢@AlexA。节省2个字节!

这遵循了我对Jelly回答的观察结果,但是对边缘情况的处理却有所不同。

如果n> 1,则n-1的二进制表示形式的位数比下一个2的幂次方的位数小一位,这可以通过不删除n的二进制表示形式的首位数来补偿。

通过消除两侧的所有零,我们也处理边缘情况1


0

Haskell,82个字节

这是Haskell中非常简单的实现:

f x=[j|j<-[1..],let g i|i<2=1|x>g(i-1)=2*g(i-1)|1<2=div(g(i-1)+g(i-2))2,g j==x]!!0

少打高尔夫球:

f x = head [ stepNum | stepNum <- [1..], step stepNum == x]
  where
    prevStep i = step (i-1)
    step i | i == 1         = 1
           | x > prevStep i = 2 * prevStep i
           | otherwise      = div (prevStep i + step (i-2)) 2
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.