Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.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
Algorithm 冷热二进制搜索游戏_Algorithm_Binary Search - Fatal编程技术网

Algorithm 冷热二进制搜索游戏

Algorithm 冷热二进制搜索游戏,algorithm,binary-search,Algorithm,Binary Search,热或冷 我想你必须做一些二进制搜索,但我不知道怎么做 你的目标是猜测一个介于1和N之间的秘密整数。你 反复猜测1到N之间的整数。每次猜测后,您将学习 如果它等于秘密整数(游戏停止);否则 (从第二个猜测开始),您可以了解猜测是否更激烈 比你的密码更接近或更冷 先前的猜测。设计了一种在lg中查找秘密号码的算法 N+O(1)猜测 提示:设计一个算法来解决lg N+O(1)中的问题 猜测假设允许猜测-N范围内的整数 到2N 我一直在绞尽脑汁,似乎想不出一个lg N+O(1) 我发现了这一点:但无法理解

热或冷

我想你必须做一些二进制搜索,但我不知道怎么做

你的目标是猜测一个介于1和N之间的秘密整数。你 反复猜测1到N之间的整数。每次猜测后,您将学习 如果它等于秘密整数(游戏停止);否则 (从第二个猜测开始),您可以了解猜测是否更激烈 比你的密码更接近或更冷 先前的猜测。设计了一种在lg中查找秘密号码的算法 N+O(1)猜测

提示:设计一个算法来解决lg N+O(1)中的问题 猜测假设允许猜测-N范围内的整数 到2N

我一直在绞尽脑汁,似乎想不出一个lg N+O(1)


我发现了这一点:但无法理解图表,也没有描述其他可能的情况。

解决方案接近于二进制搜索。在每一步中,您都有一个数字可以包含的间隔。从整个间隔开始
[1,N]
。首先猜测两端-即数字
1
N
。其中一个将更接近,因此您将知道,现在您正在搜索的数字位于
[1,N/2]
[N/2+1,N]
中(为了简单起见,请考虑N)。现在进入下一步,间隔要小两倍。继续使用相同的方法。请记住,您已经探索了其中一个端点,但这可能不是您的最后猜测


我不确定你所说的lgn+O(1)是什么意思,但我建议的方法将执行O(log(N))操作,在最坏的情况下,它将完全执行log4(N)探测。

假设你知道你的秘密整数在
[a,b]
中,并且你最后的猜测是
c

您想将间隔除以2,并知道您的秘密整数是位于
[a,m]
还是
[m,b]
之间,其中
m=(a+b)/2

诀窍是猜测
d
,这样
(c+d)/2=(a+b)/2

在不丧失一般性的情况下,我们可以假设
d
大于
c
。然后,如果
d
c
热,则您的秘密整数将大于
(c+d)/2=(a+b)/2=m
,因此您的秘密整数将位于
[m,b]
。如果
d
c
冷,您的秘密整数将属于
[a,m]

您需要能够在
-N
2N
之间进行猜测,因为您不能保证上面定义的
c
d
始终是
[a,b]
。您的两个第一猜测可以是
1
N

因此,每次猜测的间隔都是2,所以复杂度是log(N)+O(1)

一个简短的例子来说明这一点(随机选择的结果):


编辑,由@tmyklebu建议:

我们仍然需要证明,我们的猜测总是落在bewteen
[-N,2N]

通过重复,假设
c
(我们之前的猜测)在
[a-(a+b),b+(a+b)]=[-b,a+2b]

然后
d=a+b-c=-b

初始情况:
a=1,b=N,c=1
c
确实在
[-b,a+2*b]


QED

这是IOI2010的一项任务,我是主办科学委员会的成员。(我们要求的是一个最优的解决方案,而不是简单的
lgn+O(1)
,下面的不是很理想。)

不在外面摆动
-N。。2N
和使用
lgn+2
猜测很简单;你需要做的就是证明二进制搜索的明显翻译是有效的

一旦你有了一些不在外面摇摆的东西,
-N。。2N
并进行
lgn+2
猜测,执行以下操作:

猜一猜,然后猜一猜。这将告诉您答案在数组的哪一半。然后猜半个数组的末尾。你要么在两个“中间”四分之一,要么在两个“末端”四分之一。如果你在第四季度中期,在之前做这件事,你会在
lgn+4
猜测中获胜。两端稍微有些棘手


假设我需要猜一个
1。。K
不偏离
1。。N
我最后的猜测是
1
。如果我猜K/2,我更冷,那么我下一步猜1;我花了两次猜测得到了一个类似的子问题,大小为1/4。如果
K/2
更热,我知道答案在
K/4。。K
。猜下一步。这两个子类别是
K/4。。K/2-1和K/2。。K
,两者都很好。但我花了三次猜测才(在最坏的情况下)将问题的规模减半;如果我这样做,我最终会做
lgn+6
猜测。

这是我对这个问题的两分钱,因为我对它着迷了两天。我不会对其他人已经说过的话说任何新的东西,但我会以一种可能让一些人容易理解解决方案的方式来解释它(或者至少是我设法理解它的方式)

从~2 lg N溶液中提取,如果我知道溶液存在于
[a,b]
中,我想知道它是在左半部分
[a,(a+b)/2]
还是在右半部分
[(a+b)/2,b]
,点
(a+b)/2将两半分开。那我该怎么办?我猜
a
然后
b
;如果我用
b
变冷,我知道我在上(左)半场,如果我变热,我知道我在下(右)半场。因此猜测
a
b
是知道相对于中点
(a+b)/2
的秘密整数位置的方法。然而,
a
b
并不是我能猜出秘密位置的唯一点<代码>(a-1,b+1)
(a-2,b+2)
。。。etc都是有效的点对
Guess    Result    Interval of the secret number
 1       ***       [1   , N    ]    // d    =  a   +  b  - c
 N       cooler    [1   , N/2  ]    // N    =  1   +  N  - 1
-N/2     cooler    [N/4 , N/2  ]    //-N/2  =  1   + N/2 - N
 5N/4    hotter    [3N/8, N/2  ]    // 5N/4 = N/4  + N/2 + N/2
-3N/8    hotter    [3N/8, 7N/16]    //-3N/8 = 3N/8 + N/2 - 5N/4
  .        .            .               .
  .        .            .               .
  .        .            .               .
public class HotOrCold {
    static int num=5000;// number to search
    private static int prev=0;

    public static void main(String[] args) {
        System.out.println(guess(1,Integer.MAX_VALUE));
        
    }
    public static int guess(int lo,int hi) {
        while(hi>=lo) {
            boolean one=false;
            boolean two=false;
            if(hi==lo) {
                return lo;
            }
            if(isHot(lo)) {
                one=true;
            }
            if(isHot(hi)) {
                two=true;
            }
            if(!(one||two)) {
                return (hi+lo)/2;// equal distance
            }
            if(two) {
                lo=hi-(hi-lo)/2;
                continue;//checking two before as it's hotter than lo so ignoring the lo
            }
            if(one) {
                hi=lo+(hi-lo)/2;
            }
            
        }
        
        return 0;
        
    }

    public static boolean isHot(int curr) {
        boolean hot=false;
        if(Math.abs(num-curr)<Math.abs(num-prev)) {
            hot=true;
        }
        prev=curr;
        return hot;
    }
}