【问题标题】:How to avoid corner case while solving perfect square in O(lg N) time?如何在 O(lg N) 时间内求解完美平方时避免极端情况?
【发布时间】:2017-01-17 17:57:48
【问题描述】:

以下代码查找给定数字是否是 O(lg N) 中的完美平方。如何避免硬编码下面解决方案中给出的角落案例if (num === 1) { return true; }?有什么想法吗?

var isPerfectSquare = function(num) {
    let floor = 0, ceiling = num, mid;

    // Corner case
    if (num === 1) {
        return true;
    }

    while (floor != ceiling) {
        mid = floor + (ceiling - floor) / 2 | 0;
        let mul = mid * mid;

        if (mul === num) {
            return true;
        }

        if (mul > num) {
            ceiling = mid;
        }
        else if (mul < num) {
            floor = mid+1;
        }   
    }
    return false;
};

【问题讨论】:

  • @P0W 在标记为重复之前至少阅读问题的第一行。我不需要找到更快的解决方案。我的问题是关于避免极端情况。
  • @P0W,建议的欺骗被标记为 java,即使接受的答案是 C++
  • @baltusaj,是的,我知道它不是,即使不阅读问题正文也不应该被解释为这样。标签已经说不是。
  • 一个小小的改变就可以解决问题..请查看下面的解决方案

标签: javascript algorithm big-o binary-search


【解决方案1】:

通过保持一个智能不变量,我们可以将代码更改为最后只需要一次相等性检查。应该适用于所有输入

var isPerfectSquare = function(num) {
    let floor = 0, ceiling = num+1, mid;
    // We will keep the invariants: floor*floor <= num,
    //   ceiling * ceiling > num

    while (ceiling - floor > 1) {
        mid = floor + (ceiling - floor) / 2 | 0;
        let mul = mid * mid;

        // Move one of floor/ceiling to mid
        // Retains the invariant!
        if (mul > num) {
            ceiling = mid;
        } else {
            floor = mid;
        }   
    }
    return floor * floor === num;
};

我可能搞砸了语言语法,但这个想法应该可行。

【讨论】:

【解决方案2】:

您可以通过将 while 循环中的条件更改为

来避免 num==1 的特定边界情况

while (floor &lt; ceiling-1)

这就足够了,如果floorceiling 之间的差值为 1,那么您将陷入无限循环,因为在四舍五入时floor + ceiling-floor/2 将始终等于floor

我刚刚尝试了下面的 Java 实现,它看起来不错

public static void isPerfectSquare(int num){
     int low = 0;
     int high = num;
     int mid;
     while(low<high-1){
         mid = low + (high-low)/2;
         System.out.println("high-- " + high + " low-- " + low + " mid---" + mid);
         int square = mid*mid;
         if(square==num){
             System.out.println("Found ->" + mid);           
             break;
         }
         else if(square<num){
             low = mid;          
         }
         else if(square>num){
             high = mid;             
         }       
     }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    • 2018-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 2015-06-29
    相关资源
    最近更新 更多