第一题 x的平方根

题目

二分查找

对于算术平方根的计算,我们可以使用二分查找不断缩小边界,最终找到其算术平方根

具体代码

func mySqrt(x int) int {
    l, r := 0, x
    ans := -1
    for l <= r {
        mid :=  (r + l) / 2
        if mid * mid <= x {
            ans = mid
            l = mid + 1
        } else {
            r = mid - 1
        }
    }
    return ans
}

效果如下

牛顿迭代法

代码

func mySqrt(x int) int {
    if x == 0 {
        return 0
    }
    C, x0 := float64(x), float64(x)
    for {
        xi := 0.5 * (x0 + C/x0)
        if math.Abs(x0 - xi) < 1e-7 {
            break
        }
        x0 = xi
    }
    return int(x0)
}

复杂度分析

时间复杂度:O(logx)。

空间复杂度:O(1)。

第二题 两数相除

题目

思路

官解的思路较为复杂

仅供参考

对于除法
可以用更朴素的减法思维来计算
借鉴快速幂和快速乘的思想
我们从2的n次幂找起
每次找到刚好比被除数小的除数*2^n
并在结果中加入2^n

代码如下

func divide(dividend int, divisor int) int{
    if dividend == math.MinInt32 { // 考虑被除数为最小值的情况
        if divisor == 1 {
            return math.MinInt32
        }
        if divisor == -1 {
            return math.MaxInt32
        }
    }
    if divisor == math.MinInt32 { // 考虑除数为最小值的情况
        if dividend == math.MinInt32 {
            return 1
        }
        return 0
    }
    if dividend == 0 { // 考虑被除数为 0 的情况
        return 0
    }
    a := dividend
    b := divisor
    sign := 1
    if (a>0&&b<0) || (a<0&&b>0) {
        sign = -1
    }
    if a<0 {a=-a}
    if b<0 {b=-b}
    res := div(a,b)
    if sign>0{return res}else{
        return -res
    }
}
func div( a int,  b int)int {
    if a < b {
        return 0
    }
    count :=1

    tb := b // 在后面的代码中不更新b
    for (tb + tb) <= a {
        count = count + count // 最小解翻倍
        tb = tb + tb         // 当前测试的值也翻倍
    }
    return count + div(a-tb, b)
}

溢出处理可以参考官解

用减法完成除法的思想详细可以了解组成原理中定点数的除法运算

复杂度分析

时间复杂度:O(logn)。其中n为商的大小

空间复杂度:O(logn)。div中递归调用栈的最大深度为logn

03-05 14:42