1.4.34热还是冷。你的目标是猜出1到N之间的一个秘密的整数。每次猜完一个整数后,你会知道你的猜测和这个秘密整数是比较热(接近)还是比较冷(远离)。设计一个算法在~2lgN之内找到这个秘密整数,然后再设计一个算法在~1lgN之内找到这个秘密整数。
答:
1)猜1
2)猜N
3)
3.1)如果秘密数是1,猜中。
3.2) 如果秘密数是N,猜中。
3.3) 如果秘密数不是1,也不是N时如果猜N相对猜1时变热说明秘密数在N/2+1至N-1中,那么接着猜N/2、N,也可考虑猜N/2+1、N-1。
3.4)不变热时说明秘密数在2至N/2中,那么接着猜1、N/2,也可考虑猜2、N/2。
按上述过程反复执行,直到猜到为止。(由于秘密数一定是在1至N中,所以一定能猜中。)
注:由于每次猜测只能知道相对上一次猜测是变冷或变热,如果先猜小数,后猜大数,秘密数离小数近时,猜中间数一定是变热,所以每次迭代都不得不猜两个数。也就是~2lgN次。
public class E1d4d34A
{
public static void main(String[] args)
{
int N=Integer.parseInt(args[0]);
int key=Integer.parseInt(args[1]);
StdOut.printf("N=%d,key=%d,guesskey=%d",N,key,guessKey(N,key));
}//end main
public static int guessKey(int N,int key)
{
int guess1=1;
int guess2=N;
int guessResult;
while (true)
{
guessResult=guessTwoNumber(guess1,guess2,key);
StdOut.printf("guess1=%d,guess2=%d
",guess1,guess2);
if (guessResult==1)//guess1 is key
return guess1;
else if (guessResult==2)//guess2 is key
return guess2;
else if (guessResult==3)//hot
guess1=(guess1+guess2)/2;
else//cold
guess2=(guess1+guess2)/2;
}//end while
}//end guessKey
public static int guessTwoNumber(int guess1,int guess2,int key)
{
if (guess1==key)
return 1;// "guess1"
else if(guess2==key)
return 2;//"guess2"
else if(Math.abs(guess1-key) >Math.abs(guess2-key))
return 3;// "hot";
else
return 4;// "cold"
}
}//end class