[LeetCode]75. Pow(x,n)幂运算
Implement pow(x, n).
Subscribe to see which companies asked this question
解法1:最简单的即是n个x直接相乘,毫无疑问会超时Time Limit Exceeded
class Solution { public: double myPow(double x, int n) { if(x < 0.000001) return 0; if(n == 0) return 1; if(n < 0) return 1.0 / myPow(x, -n); double res = 1.0; for(int i = 0; i < n; ++i) res *= x; return res; } };
解法2:考虑pow(4,12),可以这样计算:pow(4,12)=pow(4,8)*pow(4,4),而pow(4,8)可以通过pow(4,1)-->pow(4,2)-->pow(4,4)-->pow(4,8)这样计算,pow(4,4)同样可以通过可以通过pow(4,1)-->pow(4,2)-->pow(4,4)计算得到。即在计算到某次幂pow(x,k)的时候,若当前幂次的平方pow(x,2k)不会大于结果(通过2k<=n来判断),则直接平方。因此可以写出如下代码:
class Solution { public: double myPow(double x, int n) { if (x < 0.000001) return 0; if (n == 0) return 1; if (n < 0) return 1.0 / myPow(x, -n); double res = 1.0; while (n > 0) { double f = x; int loop = 1; while ((loop << 1) <= n) { f *= f; loop <<= 1; } n -= loop; res *= f; } return res; } };
这样虽然一定程度上减少了运算次数,但是正如上面例子展现的,仍然会有不少的冗余计算。同样在LeetCode中提交后会超时Time Limit Exceeded。可以使用map<double,int>记录下计算过的幂值,第一次循环后后面的所有值都可以通过查表得到,这样可以减少重复计算。
class Solution { public: double myPow(double x, int n) { if (x == 0) return 0; if (n == 0) return 1; if (n < 0) return 1.0 / myPow(x, -n); vector<double> power; double res = 1.0; double f = x; int loop = 1; power.push_back(f); while ((loop << 1) <= n) { f *= f; power.push_back(f); loop <<= 1; } n -= loop; res *= f; bitset<sizeof(int) * 8> powb(n); for (int i = 0; i < 32; ++i) { if (powb[i] == 1) res *= power[i]; } return res; } };
但是这种方法会出现 Memory Limit Exceeded。因为输入指数为int型,实际vector<double>最大长度为32,是常数复杂度。时间复杂度也在常数级别。不知题目限定空间复杂度在什么级别。
解法3:考虑使用二分搜索。如果n为偶数,则pow(x,n)=pow(x,n/2)*pow(x,n/2),如果n是奇数则再乘个x。这样递归下去,直到n==0。
class Solution { public: double myPow(double x, int n) { if (x == 0) return 0; if (n == 0) return 1; if (n < 0) return 1.0 / power(x, -n); return power(x, n); } private: double power(double x, int n) { if (n == 0) return 1; double half = power(x, n / 2); double res = half * half; return n % 2 == 0 ? res : res * x; } };