先从LeetCode一个题目开始:50.Pow(x, n)
题目的要求是计算x的n次幂,注意n可能为负数,这道题比较直观的解法是模拟,即将x乘n次,最后将结果返回,时间复杂度是O(n),时间复杂度还是比较高的,如果n比较大的话要执行多次循环,我们可以将时间复杂度降低到O(log(n)),这就是快速幂思想。
我们可以想象一下方法1的模拟思想为什么那么慢,这是因为乘以x的步骤执行了太多次,实际上我们可以这样运算,假设x ^ n = (x ^ (n / 2)) *( x ^ (n / 2)),一直这样分解,直到 x ^ n == 1,这样我们就只需要知道 x ^ (n / 2) 的结果,我们就足够知道x ^ n,进而推出x ^ (2n),直到指数到达题目要求的幂,这是从左向右进行推导,但是在分解(n = n / 2)的过程中,我们丢失了要乘的x(n为奇数,除了2,就丢失了一个1),这时我们必须将结果额外乘以一个x以补齐,这样我们倒过来进行分解,当n是偶数时,扩大基数x,当n是奇数时,我们就要对结果乘以一个x以补齐丢失的x。
class Solution {
public double myPow(double x, int n) {
double res = 1;
long m = n;
if (n < 0) {
m = Math.abs(n - 1) - 1;;
}
while (m > 0) {
if (m % 2 == 1) {
res *= x;
}
m = m >> 1;
x *= x;
}
return n < 0 ? (double) 1 / res : res;
}
}