java - 如何正确实现二分搜索算法来猜测 Java 中的随机 BigInteger?

标签 java search biginteger

我正在编写一个程序,该程序应该猜测另一个程序随机生成的 BigInteger。数字类提供关于我的猜测是否高于或低于数字的反馈(如果答案正确,则为“正确”)。虽然我的程序运行良好并正确猜测 BigInteger,但我实现的二分搜索算法的执行效率低于我的预期。我绞尽脑汁也想不通为什么猜测次数(找到该位后)超过了 log(n) 时间。

我一直在计算猜测的数量,并且我的代码的第一部分(找到大整型的正确位)表现得非常好,通常只需要少量猜测。

public static BigInteger guesser(Number n) {
    int guesses=0;

    String feedback = n.guess(BigInteger.ONE); 
    guesses++;

    if (feedback.equals("correct")){
        return BigInteger.ONE;

    } else{
        BigInteger two = new BigInteger("2");
        BigInteger max = two;
        BigInteger min = max;
        BigInteger mid;

        if(n.guess(max).equals("correct")) {
            return max;
        }

        while (!feedback.equals("lower")) {
            min = max;
            max = max.pow(2);
            feedback=n.guess(max); 
                    guesses++;
        }

        mid = min.add(max).divide(two);
        feedback = n.guess(mid); 
            guesses++;

        while (!feedback.equals("correct")){
            if (feedback.equals("higher")){
                min=mid.add(BigInteger.ONE);
            } else if (feedback.equals("lower")){
                max=mid.subtract(BigInteger.ONE);
            } 
            mid= min.add(max).divide(two);
            feedback = n.guess(mid); 
                guesses++;
        }
        return mid;
    }

代码的二分搜索算法部分进行了大量的猜测,我不明白为什么。对于 38119 位 BigInteger,程序大约需要两倍的猜测次数。我是否在做一些根本性错误的事情,或者这里是否有一个我忽略的简单错误?猜测次数不应该大约等于2log(n)吗?

最佳答案

问题是你的指数搜索走得太高了。当数字足够大时,您找到的第一个数字比需要的要高得多。

假设您要猜测的数字是 43263289412904812894021841098214912804215324,通过应用 pow(2) 查找上限,您要猜测的第一个数字是 115792089237316195423570985008687907853269984665640564039457584007913129639936 - 这要高得多,需要多次尝试才能返回到附近。

现在假设您应用了 multiply(new BigInteger("25")) - 您输入的第一个数字是 43368086899420177360298112034797668457031250。是的,需要更多的尝试才能达到这个数字,但最终这是值得的,因为在如此巨大的数字上的最后一个 pow(2) 造成了如此大的杀伤力,以至于很难回来。我在这里使用了一个小数字,但数字越大,情况就越糟糕。

在我看来 - 在寻找上限的同时,你应该在应用 pow 和乘法之间找到平衡。也许如果一个数字足够大,那么停止求幂并开始乘以某个值,并随着界限变高而使该值变高。

我在上面的示例中使用了一个较小的值,但使用 38119 位 BigInteger:

  • pow(2) - 上限 17 个猜测 - 所有猜测 65552
  • multiply(new BigInteger("25")) - 上限 8209 个猜测 - 所有猜测 46327 个
  • multiply(new BigInteger("100")) - 上限 5738 个猜测 - 所有猜测 43854 个
  • multiply(new BigInteger("1000")) - 上限 3826 个猜测 - 所有猜测 41946 个
  • multiply(new BigInteger("10000")) - 上限 2870 个猜测 - 所有猜测 40994 个
  • multiply(new BigInteger("50000")) - 上限 2443 个猜测 - 所有猜测 40562 个
  • multiply(new BigInteger("100000")) - 上限 2296 个猜测 - 所有猜测 40416

需要进行更多猜测才能达到上限,但随后我们更接近最终值,因此仍然值得。请注意,它在某个时候不再有值(value)。

关于java - 如何正确实现二分搜索算法来猜测 Java 中的随机 BigInteger?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54153585/

相关文章:

java - 单击操作栏图标时弹出菜单

ios - Couchbase lite,搜索查询花费很长时间

python - 如何像在 Python 2.7 上一样快地获取此 Python 3 代码?

java - org.hibernate.AnnotationException : Unknown Id. 生成器:GenreIdGenerator

java - 使用 Java 8 将字符串转换为对象列表

mysql - 使用 "like"和 "match()"进行等效搜索

c# - 二进制搜索算法查找排序数组中值的变化

c# - 针对 net45 时的 System.Numerics

java - 将 Java BigInteger 用于巨大位掩码的性能影响

java - 单例模式是 RedissonClient 的一个很好的用例吗?