快速求一个整数的平方根

简单的迭代法:

int sqrt(int N)
{
    for (int i = 1; i <= N / 2; i++)
    {
        if(i * i == N ) {
            return i;
        }
        if (i * i < N && (i + 1) * (i + 1) > N) {
            return i;
        }
    }
}

折半迭代法(老师给的方法):

int sqrt(int N)
{
    int first = 1, last;
    while(1) {
        last = N / first;
        first = (first + last) / 2;
        if (first == last || first == last - 1) {
            return first;   
        }
    }
    return 0;
}

关于折半法的解释:

last = N / first 可以看出 N = first * last,结合下面的 first = (first + last) / 2 可知,每一次循环都会把寻找的数的数量规模缩减为原来的一半,我们简单思考一下,先来两个实例帮助理解:

求 20 的整数平方根:

first last
1 20
10 2
6 3
4 5

求 25 的整数平方根:

first last
1 25
13 1
7 3
5 5

我们知道,每一次迭代的时候,first和last的乘积都是N,在不能恰好开方的时候,如果last - first != 1,那么我们所求的最后的结果必定存在于first和last之间,然后我们再在下一次的迭代中将last置为N/first,first置为first和last的中间值,每一次的迭代我们都在向最终的first和last接近,使得first * first < N, last * last > N,同时last - first == 1,此时first就是我们所要求的结果。对于恰好能开方的情况,就可以同理了。

此算法时间复杂度为 \(O(log N)\)


更新:

同样是折半查找,我觉得下面的算法更容易理解一些(参考了 LeetCode 的题解):

public int mySqrt(int x) {
    if (x == 1) {
        return 1;
    }
    int min = 0;
    int max = x;
    while (max - min > 1) {
        int m = (max + min) / 2;
        if (x / m < m) { // 这里也可以用乘法,应该要更快一点
            max = m;
        } else {
            min = m;
        }
    }

    return min;
}

注意,这里是 Java 代码。

posted @ 2020-09-29 11:46  模糊计算士  阅读(695)  评论(0编辑  收藏  举报