一起刷LeetCode——pow(x,n)(分治)

77 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第19天,点击查看活动详情

pow(x,n)

实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即,x的n次方 )。

来源:力扣(LeetCode)链接:leetcode.cn/problems/po…

分析

递归

  • 计算x的n次方,属于幂运算,幂运算有这样一条法则:(a^n)^m= a^(m*n)
  • 基于幂运算的基本法则,在算x的n次方的时候,可以不用x连乘n次,就大大减少了运算次数,那怎样做才是最少的次数?比较容易想到二分法+递归,每次递归n减少一半,如果n是偶数就正好是n/2次,如果是奇数,二分后再乘一次x
  • 最后根据n是正数还是负数返回结果
代码
var myPow = function(x,n){
    if(n == 0) {
        return 1
    }
    if(n<0){
        return myPow(1/x, -n)
    }
    if(n%2 === 0){
        let n = myPow(x, n/2)
        return n*n
    } else {
        let n = myPow(x, (n-1)/2)
        return n*n*x
    }
}

迭代

  • 因为递归需要额外的栈,空间复杂度为O(logn),可以换另一种思路,使用迭代的解法
  • 幂运算除了上面提到的,还有一个是(x^m)*(x^n) = x^(m+n)
  • 把n拆成几个数相加,把这几个数当成x的幂,几个幂的运算结果相乘,即可得出结论
  • 在拆数这部分,也不是随便拆的,计算机擅长的是二进制,这里可以把十进制n拆成几个二进制相加,即x^n = (x^a)*(x^b)*...*(x^m),a+b+...+m = n,2^k0 = a,2^k1 = b,...,所以当[k0,k1...kx]中为0的时候,是当前结果的平方,为1的时候需要乘当前x,最后得出结果
代码
var myPow = function(x, n) {
  const on = n;
  let ans = 1;
  n = [...Math.abs(n).toString(2)];
  while(n.length) {
    const instruction = n.shift(); 
    switch(instruction) {
      case "0": 
        ans *= ans; 
        break;
      case "1":
        ans *= ans;
        ans *= x; 
        break;
    }
  } 
  return on < 0 ? 1/ans : ans;
};

总结

  • 今天的题目难度等级为中等,主要用分治的思想,把一个问题分成2个或者多个向上的子问题,再把子问题分成更小的问题,最后得到结果
  • 世界的尽头是数学,算法的尽头也是数学
  • 基础的数学运算、数学方法、定理、公理常驻大脑内存,解题会更加有思路
  • 今天也是有收获的一天