Implement pow(x, n), which calculates x raised to the power n (xn).
Example 1:
Input: 2.00000, 10
Output: 1024.00000
Example 2:
Input: 2.10000, 3
Output: 9.26100
Example 3:
Input: 2.00000, -2
Output: 0.25000
Explanation: 2-2 = 1/22 = 1/4 = 0.25
Note:
-100.0 < x < 100.0
n is a 32-bit signed integer, within the range [−231, 231 − 1]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/powx-n
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这个问题其实就是自己写一个Pow函数,来计算x的n次幂
假设要求 2 48 = 2 24 ∗ 2 24 = 2 12 ∗ 2 12 ∗ 2 12 ∗ 2 12 = 2 6 ∗ 2 6 ∗ 2 6 ∗ 2 6 ∗ 2 6 ∗ 2 6 ∗ 2 6 ∗ 2 6 = 2 3 ∗ 2 3 ∗ 2 3 ∗ 2 3 ∗ 2 3 ∗ 2 3 ∗ 2 3 ∗ 2 3 ∗ 2 3 ∗ 2 3 ∗ 2 3 ∗ 2 3 ∗ 2 3 ∗ 2 3 ∗ 2 3 ∗ 2 3 2^{48}=2^{24}*2^{24}=2^{12}*2^{12}*2^{12}*2^{12}=2^{6}*2^{6}*2^{6}*2^{6}*2^{6}*2^{6}*2^{6}*2^{6}=2^{3}*2^{3}*2^{3}*2^{3}*2^{3}*2^{3}*2^{3}*2^{3}*2^{3}*2^{3}*2^{3}*2^{3}*2^{3}*2^{3}*2^{3}*2^{3} 248=224∗224=212∗212∗212∗212=26∗26∗26∗26∗26∗26∗26∗26=23∗23∗23∗23∗23∗23∗23∗23∗23∗23∗23∗23∗23∗23∗23∗23…
因为我还是更加熟悉c#/Java所以先选择了Java
import java.util.Scanner;
class Main{
public static void main(String[] args) {
double x;
int n;
Scanner sc = new Scanner(System.in);
System.out.println("Pls input x");
x = sc.nextDouble();
System.out.println("Pls input n");
n = sc.nextInt();
System.out.println(myPow(x, n));
}
static double myPow(double x, int n) {
int N = n;
if (n == 0)
return 1;
return N > 0 ? CalPow(x, N) : 1 / CalPow(x, -N);
}
static double CalPow(double x, int N)
{
if (N == 1)
return x;
int n = N / 2;
if (N % 2 != 0)
{
return x * CalPow(x, n) * CalPow(x, n);
}
return CalPow(x, n) * CalPow(x, n);
}
}
一跑发现有溢出了,大晚上脑子有点懵,还以为是double溢出,但是浮点数是以 符号 指数 小数 来储存的,不太可能溢出啊。后来看了看大佬们的题解,才发现是在N取-128的时候变成正数造成的溢出
所以还是得谨慎一点才行
修改之后
import java.util.Scanner;
class Main{
public static void main(String[] args) {
double x;
int n;
Scanner sc = new Scanner(System.in);
System.out.println("Pls input x");
x = sc.nextDouble();
System.out.println("Pls input n");
n = sc.nextInt();
System.out.println(myPow(x, n));
}
static double myPow(double x, int n) {
long N = n;
if (n == 0)
return 1;
return N > 0 ? CalPow(x, N) : 1 / CalPow(x, -N);
}
static double CalPow(double x, long N)
{
if (N == 1)
return x;
int n = (int)N / 2;
if (N % 2 != 0)
{
return x * CalPow(x, n) * CalPow(x, n);
}
return CalPow(x, n) * CalPow(x, n);
}
}
舒服多了,可是新的问题又产生了。对,就是该死的超时,递归的时候我每次都要再重新算一遍结果,然后它就超时了
import java.util.Scanner;
class Main{
public static void main(String[] args) {
double x;
int n;
Scanner sc = new Scanner(System.in);
System.out.println("Pls input x");
x = sc.nextDouble();
System.out.println("Pls input n");
n = sc.nextInt();
System.out.println(myPow(x, n));
}
static double myPow(double x, int n) {
long N = n;
if (n == 0)
return 1;
return N > 0 ? CalPow(x, N) : 1 / CalPow(x, -N);
}
static double CalPow(double x, long N)
{
if (N == 1)
return x;
double num = CalPow(x, N / 2);
if (N % 2 != 0)
{
return x * num * num;
}
return num * num;
}
}
OK,问题解决!
class Solution {
public:
double quickMul(double x, long long N) {
double ans = 1.0;
// 贡献的初始值为 x
double x_contribute = x;
// 在对 N 进行二进制拆分的同时计算答案
while (N > 0) {
if (N % 2 == 1) {
// 如果 N 二进制表示的最低位为 1,那么需要计入贡献
ans *= x_contribute;
}
// 将贡献不断地平方
x_contribute *= x_contribute;
// 舍弃 N 二进制表示的最低位,这样我们每次只要判断最低位即可
N /= 2;
}
return ans;
}
double myPow(double x, int n) {
long long N = n;
return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N);
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/powx-n/solution/powx-n-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
嚯,真是妙啊。
因为每个 x n x^n xn都会被拆成 x n / 2 ∗ x n / 2 x^{n/2}*x^{n/2} xn/2∗xn/2或者是 x n / 2 ∗ x n / 2 ∗ x x^{n/2}*x^{n/2}*x xn/2∗xn/2∗x
假设我们要求 x 77 x^{77} x77
那么 x → x 2 → x 4 → x 9 → x 19 → x 38 → x 77 x \rightarrow x^{2} \rightarrow x^{4} \rightarrow x^{9} \rightarrow x^{19} \rightarrow x^{38} \rightarrow x^{77} x→x2→x4→x9→x19→x38→x77
其中在 x 77 x^{77} x77、 x 19 x^{19} x19、 x 9 x^{9} x9在拆分的时候要多拆一个x
x 77 x^{77} x77被拆开时,需要多乘一个 x x x
x 19 x^{19} x19被拆开时,需要多乘四个 x x x,就有 2 2 = 4 2^{2}=4 22=4
x 9 x^{9} x9被拆开时,需要多乘八个 x x x,就有 2 2 2 = 8 2^{2^2}=8 222=8
然后最初的 x x x被拆了6次,那么就有 2 6 = 64 2^6=64 26=64
将它们全部相乘 x ∗ x 4 ∗ x 8 ∗ x 64 x*x^4*x^8*x^{64} x∗x4∗x8∗x64结果正好为 x 77 x^{77} x77
而其中的1,4,8,64 恰好又是77的二进制数 ( 1001101 ) 2 (1001101)_2 (1001101)2中的每个1
这个题自己犯错的主要问题就是没有考虑全面,多注意一些小细节,以及多思考怎样才能计算次数更少才行,一开始return 函数*函数那就要多算很多遍。
一些问题可以尝试从二进制下手,只要找出其中的规律,解决问题所需的时间和空间可能会大大减少。