LeetCode(69)Sqrt

题目如下:

Implement int sqrt(int x).
Compute and return the square root of x.

分析如下:

(1)借助一个小结论,任何一个数的square都在大于等于1,小于x/2+1。很容易反证。

(2)第一次提交,发现溢出了。因为不是low, hight, mid用的类型是int,所以mid*mid可能会溢出。所以应该把数据类型设为long long。

(3)本质思想还是二分查找。

我的代码:

class Solution {
public:
    int sqrt(int x) {
        long long low=1;
        long long high=x/2+1;
        long long mid=0;
        if(x==1)
            return 1;
        if(x<=0)
            return 0;
        while(low<=high){ //这里是low<=high而不是low<high,理由是,当low=high时,可能还没找到正确值,需要在进入循环体更新一次。可用sqrt(5)来验证。
            mid=low+(high-low)/2;
            if(mid*mid>x)
                high=mid-1;
            else if(mid*mid<x)
                low=mid+1;
            else
                return mid;
        }
        return (low+high)/2;//注意这里是返回新的mid,也就是(low+high)/2,而不是旧的mid。如果写return mid,就将返回旧的mid,有错。
    }
};

update 2014-12-30

解法一: 迭代

/*
*解法一:迭代
*1. 一个数n的平方根一定小于等于(n/2 + 1), 二分法查找(递归和迭代)。
*2. 可能是平台的问题,如果用unsinged long long 而不是long long型的话,答案会有问题。
*3. while(start <=end)这里的条件是“小于等于”。
4.  迭代到最后,可能出现的情况打印出来看有两种,观察可以发现,循环结束的时候, sqrt = start - 1。
    case 1:达到相等点之后走向相等点的左边
        input=5
        start = 1, end = 3, mid = 2
        start = 3, end = 3, mid = 3 //达到相等点(3)之后走向相等点的左边
        start = 3, end = 2, x = 5
        real sqrt=2, my sqrt =2
        
    case 2:不达到相等点,直接走向相等点的左边
        input=6
        start = 1, end = 4, mid = 2
        start = 3, end = 4, mid = 3 //不达到相等点,到达两个相邻点(3, 4), 直接走向相邻点的左边
        start = 3, end = 2, x = 6
        real sqrt=2, my sqrt =2
*/
//84ms
class Solution {
public:
    long long sqrt(long long x, long long start, long long end) {
        while (start <= end) {
            long long mid = start + (end - start) / 2;
            //std::cout<<"start = "<<start<<", end = "<<end<<", mid = "<<mid<<std::endl;
            if (mid * mid == x)
                return mid;
            else if (mid * mid > x)
                end = mid - 1;
            else
                start  = mid + 1;
        }
        //std::cout<<"start = "<<start << ", end = "<<end<<", x = " << x<<std::endl;
        return start - 1;
    }
    int sqrt(int x) {
        if (x < 0) return -1;
        if (x == 0) return 0;
        if (x == 1) return 1;
        return (int)sqrt(x, 1, x/2 + 1);
    }
};

解法二: 递归看上更好懂,可以避免处理循环结束时候的情况。

//解法二: 递归
//84ms 
class Solution {
public:
    long long sqrt(long long x, long long start, long long end) {
        long long mid = start + (end - start)/2;
        if (mid * mid <= x && (mid + 1) * (mid + 1) > x) return mid;
        else if (mid * mid > x) return sqrt(x, start, mid-1);
        else if (mid * mid < x) return sqrt(x, mid + 1, end);
    }
    int sqrt(int x) {
        if (x < 0) return -1;
        if (x == 0) return 0;
        if (x == 1) return 1;
        return (int)sqrt(x, 1, x);
    }
};

解法三: newton's method

//解法3: newton's method
//76ms
class Solution {
public:
    long long sqrt_my(long long x) {
        long long guess = x/2 + 1; //注意这里不能写错数据类型,如果long long写为long或者int都会导致错误。
        while (1) {
            if (guess * guess <= x && (guess + 1) * (guess + 1) > x)
                return guess;
            guess =(guess + x/guess)/2;
        }
    }
    int sqrt(int x) {
        return sqrt_my((long long)x);
    }
};



你可能感兴趣的:(LeetCode,二分查找)