文章目录
剑指Offer(第二版)之数学运算系列算法
1.Pow(x,n)
1.1快速幂+递归
func myPow(x float64, n int) float64 {
if n >= 0 {
return quickMul(x, n)
}
return 1.0 / quickMul(x, -n)
}
func quickMul(x float64, n int) float64 {
if n == 0 {
return 1
}
y := quickMul(x, n/2)
if n%2 == 0 {
return y * y
}
return y * y * x
}
//时间复杂度:O(\log n)O(logn),即为递归的层数。
//空间复杂度:O(\log n),即为递归的层数。这是由于递归的函数调用会使用栈空间。
1.2快速幂+迭代
func myPow(x float64, n int) float64 {
if n >= 0 {
return quickMul(x, n)
}
return 1.0 / quickMul(x, -n)
}
func quickMul(x float64, N int) float64 {
ans := 1.0
// 贡献的初始值为 x
x_contribute := x
// 在对 N 进行二进制拆分的同时计算答案
for N > 0 {
if N % 2 == 1 {
// 如果 N 二进制表示的最低位为 1,那么需要计入贡献
ans *= x_contribute
}
// 将贡献不断地平方
x_contribute *= x_contribute
// 舍弃 N 二进制表示的最低位,这样我们每次只要判断最低位即可
N /= 2
}
return ans
}
//时间复杂度:O(logn),即为对n 进行二进制拆分的时间复杂度。
//空间复杂度:O(1)。
2.剑指Offer46–数值的整数次方
2.1快速幂+递归
func myPow(x float64, n int) float64 {
if n >= 0 {
return quickMul(x, n)
}
return 1.0 / quickMul(x, -n)
}
func quickMul(x float64, n int) float64 {
if n == 0 {
return 1
}
y := quickMul(x, n/2)
if n%2 == 0 {
return y * y
}
return y * y * x
}
3.数字1的个数
3.1枚举
func countDigitOne(n int) (ans int) {
for i := 1; i <= n; i = i * 10 {
high := n / (i * 10) * i
low := min(max(n%(i*10)-i+1, 0), i)
ans = ans + high + low
}
return
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
//时间复杂度:O(logn)。n 包含的数位个数与 n 呈对数关系。
//空间复杂度:O(1)。
题解在此
4.剑指Offer43–1~n整数中1出现的次数
4.1枚举
func countDigitOne(n int) (ans int) {
for i := 1; i <= n; i = i * 10 {
high := n / (i * 10) * i
low := min(max(n%(i*10)-i+1, 0), i)
ans = ans + high + low
}
return
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
//时间复杂度:O(logn)。n 包含的数位个数与 n 呈对数关系。
//空间复杂度:O(1)。
题解在此