題目地址:
https://leetcode.com/problems/powx-n/
快速冪(exponentiating by squaring)。基本思路是,要求,我們可以先計算,然後再回去求,這類似於分治法,可以降低複雜度。有遞歸和非遞歸兩種寫法。
法1:含遞歸。由於測試數據裏有一個n取Integer.MIN_VALUE
這個樣例,而這個值在計算機裏是沒有相反數的(也就是對於這個數,,不存在其對應的正數),所以要用long來做。代碼如下:
public class Solution {
public double myPow(double x, int n) {
return pow(x, n);
}
// 要用long來做
private double pow(double x, long n) {
// base case是n = 0的情況
if (n == 0) {
return 1.0;
}
// 如果n爲負,就調整爲正數來做。
if (n < 0) {
n = -n;
x = 1.0 / x;
}
// 分治
double half = pow(x, n / 2);
// 根據n的奇偶性來決定要不要額外乘一個x
if (n % 2 == 0) {
return half * half;
} else {
return half * half * x;
}
}
}
時空複雜度。
法2:非遞歸寫法。主要思路是對做二進制展開,然後對這些二進制位從右向左掃描,用一個變量來保存到當前這個二進制位,的那麼多次次方的結果是多少。
舉個例子來說,如果要算,由於,首先保存的是是多少,也就是,那其實就是。接着開始從右向左掃描,掃描到第位時遇到,就給乘上,同時需要平方一下,這樣就保存了這個值,掃描到第位時遇到,保持原樣,而繼續平方一下,得到了,繼續掃描到,這時乘一下,如此下去又乘了,掃描結束。我們統計一下會發現,,正好是所求結果。
代碼如下:
public class Solution {
public double myPow(double x, int n) {
return pow(x, n);
}
private double pow(double x, long n) {
if (n < 0) {
n = -n;
x = 1.0 / x;
}
double res = 1.0;
while (n > 0) {
if (n % 2 != 0) {
res *= x;
}
x *= x;
n >>= 1;
}
return res;
}
}
時間複雜度,空間。