Leetcode -- Pow(x, n)
2015-01-28 18:10
405 查看
https://oj.leetcode.com/problems/powx-n/
Implement pow(x, n).
public double pow(double x, int n)
问题分析:这题当然不是让你做一个计数器然后一次一次的乘下去。这题有一个test case里n是Integer.MIN_VALUE,乘20多亿次,必然是要超时的。这题的tricky point在于n上,正常来说n也应该是double,但是这里n是一个整型数,所以这题的本质换过来看其实是一个二进制题。
其实这一题换一种简单的说法就是如何用二进制来表达n。理由如下:
res = res时, n = 1, 第一次res *= res时,n = 2,第二次 res *= res时, n = 4,第三次 res *= res时, n = 8....相信你们已经看见规律了。左边是不停的自己乘自己,右边就相当于n = 1 << k
所以我们只需要让这个过程继续下去,我们同时记录 1 << k的k 和对应的res值。直到某个 1 << i 大于 n时,就可以停止了。这个时候我们就可以通过我们已有的k 和对应的res值来拼凑出n所对应的res来了。另外所需要注意的就是是否过界和负数了,另外Integer.MIN_VALUE依旧是要注意的。
给出代码如下:
update一下:最近越来越发现上面这个做法很难理解的同时也很冗余。虽然原理基本是正确的。重新做了一次,更新一下代码:
前面基本都对,回收所有 1 << x 对应的 pow(cache, 1 << x),然后下一步直接通过二进制来重构n,并且乘以对应的cache就可以了。
2017-12-02 Updated
经过再一次的思考把cache数组给省掉了,顺便就是一个for loop就搞定了,代码也简洁了些许
public double myPow(double x, int n) {
boolean isNeg = false;
double res = 1.0;
if (n < 0) {
isNeg = true;
if (n == Integer.MIN_VALUE) {
n++;
res *= x;
}
n *= -1;
}
double xCache = 1.0;
for (int i = 0; i < 32 && n != 0; i++) {
xCache = i == 0 ? x : xCache * xCache;
if ((n & (1 << i)) != 0) {
n -= 1 << i;
res *= xCache;
}
}
if (isNeg) res = 1 / res;
return res;
}
不容易啊不容易。囧
Implement pow(x, n).
public double pow(double x, int n)
问题分析:这题当然不是让你做一个计数器然后一次一次的乘下去。这题有一个test case里n是Integer.MIN_VALUE,乘20多亿次,必然是要超时的。这题的tricky point在于n上,正常来说n也应该是double,但是这里n是一个整型数,所以这题的本质换过来看其实是一个二进制题。
其实这一题换一种简单的说法就是如何用二进制来表达n。理由如下:
res = res时, n = 1, 第一次res *= res时,n = 2,第二次 res *= res时, n = 4,第三次 res *= res时, n = 8....相信你们已经看见规律了。左边是不停的自己乘自己,右边就相当于n = 1 << k
所以我们只需要让这个过程继续下去,我们同时记录 1 << k的k 和对应的res值。直到某个 1 << i 大于 n时,就可以停止了。这个时候我们就可以通过我们已有的k 和对应的res值来拼凑出n所对应的res来了。另外所需要注意的就是是否过界和负数了,另外Integer.MIN_VALUE依旧是要注意的。
给出代码如下:
public double pow(double x, int n) { if(n == 0) return 1.0; boolean isMin = false; if(n == Integer.MIN_VALUE){ isMin = true; n += 1; } boolean isNeg = n < 0; n = isNeg ? -n : n; int two_level = 0; double res = 1.0; double[] cached = new double[32]; int counter = 0; while(n > two_level){ if(two_level << 1 < two_level) break; cached[counter] = res; counter++; if(two_level == 0){ res = x; two_level = 1; } else{ res *= res; two_level = two_level << 1; } } int diff = two_level - n; boolean isDiffNeg = diff < 0; diff = Math.abs(diff); while(diff > 0){ if((diff & (1 << counter)) != 0){ diff -= 1 << counter; res = isDiffNeg ? res * cached[counter + 1] : res / cached[counter + 1]; } counter--; } if(isNeg) res = 1.0 / res; if(isMin) res /= x; return res; }
update一下:最近越来越发现上面这个做法很难理解的同时也很冗余。虽然原理基本是正确的。重新做了一次,更新一下代码:
public double pow(double x, int n) { double result = 1.0; if(n == Integer.MIN_VALUE){ result *= x; n++; } boolean isNeg = false; if(n < 0){ isNeg = true; n = -n; } int currentBit = 0; double cache = x; double[] cached = new double[32]; while((1 << currentBit) <= n && currentBit < 32){ cached[currentBit] = cache; cache = cache * cache; currentBit++; } int bit = 0; while(n != 0){ if((n & (1 << bit)) != 0){ result *= cached[bit]; n = n & (n - 1); } bit++; } return isNeg ? 1.0 / result : result; }
前面基本都对,回收所有 1 << x 对应的 pow(cache, 1 << x),然后下一步直接通过二进制来重构n,并且乘以对应的cache就可以了。
2017-12-02 Updated
经过再一次的思考把cache数组给省掉了,顺便就是一个for loop就搞定了,代码也简洁了些许
public double myPow(double x, int n) {
boolean isNeg = false;
double res = 1.0;
if (n < 0) {
isNeg = true;
if (n == Integer.MIN_VALUE) {
n++;
res *= x;
}
n *= -1;
}
double xCache = 1.0;
for (int i = 0; i < 32 && n != 0; i++) {
xCache = i == 0 ? x : xCache * xCache;
if ((n & (1 << i)) != 0) {
n -= 1 << i;
res *= xCache;
}
}
if (isNeg) res = 1 / res;
return res;
}
不容易啊不容易。囧
相关文章推荐
- Leetcode | Pow(x, n)
- 【leetcode】Pow(x, n)
- [LeetCode]pow(double x,int n)解题报告
- LeetCode 050 Pow(x, n)
- LeetCode Pow(x, n)
- LeetCode-50-Pow(x, n) 快速幂
- 【LeetCode练习题】Pow(x, n)
- [Leetcode ??] 50 Pow(x, n)
- [week 13][Leetcode][Divide and Conquer] Pow(x, n)
- [leetcode] Pow(x, n)
- [leetcode] Pow(x, n)
- Pow(x, n)--LeetCode
- [LeetCode]050-Pow(x,n)
- LeetCode | Pow(x, n)
- Leetcode习题:Pow(x, n)
- 【Leetcode】Pow(x,n)
- 【LeetCode with Python】 Pow(x, n)
- [LeetCode] Pow(x, n)
- Leetcode 50 Pow(x, n)
- LeetCode – Refresh – Pow(x, n)