题目
思路
题目很简单,对于这道题,最开始肯定想到暴力破解,但是这道题的数据太大了,
暴
力
破
解
的
时
间
复
杂
度
是
O
(
n
)
暴力破解的时间复杂度是O(n)
暴力破解的时间复杂度是O(n),所以直接放弃。
接下来很容易想到,
当
不
断
对
结
果
取
平
方
时
只
需
要
循
环
log
2
n
,
也
就
是
时
间
复
杂
度
降
为
了
O
(
log
2
n
)
。
当不断对结果取平方时只需要循环\log_2n,也就是时间复杂度降为了O(\log_2n)。
当不断对结果取平方时只需要循环log2n,也就是时间复杂度降为了O(log2n)。
只不过还是太年轻了,做题太少,代码能力不足
我
一
开
始
想
到
的
是
将
n
拆
分
为
类
似
15
=
2
3
+
2
2
+
2
1
+
2
0
的
形
式
结
果
发
现
这
样
要
从
2
x
寻
找
,
会
花
费
时
间
与
空
间
我一开始想到的是将n拆分为类似 15={2}^3 + {2}^2 + {2}^1 + {2}^0的形式 结果发现这样要从 {2}^x 寻找,会花费时间与空间
我一开始想到的是将n拆分为类似15=23+22+21+20的形式结果发现这样要从2x寻找,会花费时间与空间,且和我上面的思路有些区别,最后看了题解才明白我的思路换成数学应该是15 = 2 × 7 + 1 = 2 × (2 × 3 + 1) + 1 = 2 × (2 × (2 × 1 + 1) + 1) + 1
这
种
思
路
就
可
以
从
题
目
给
出
的
n
入
手
,
也
就
是
将
n
转
化
为
2
进
制
,
运
用
分
治
法
的
思
想
,
因
为
x
n
=
x
1
2
×
x
1
2
这种思路就可以从题目给出的n入手,也就是将n转化为2进制,运用分治法的思想,因为{x}^n = {x}^\frac{1}{2} × {x}^\frac{1}{2}
这种思路就可以从题目给出的n入手,也就是将n转化为2进制,运用分治法的思想,因为xn=x21×x21,用递归的方法,从1开始乘x,当有余数时,当前值再乘x,就可得结果,还有一种迭代的方法类似,只不过迭代是从后往前,而递归是从前往后。
迭代有一点区别是,从后往前除,越前面的数,参与过的平方次数就越多,例如上面15中,第一次取余得到的1,参与过0次平方运算,第二次取余得到的1参与过1次平方运算,所以我们要留一个空间来记录当前余数经历过几次平方运算。
代码
递归算法
class Solution {
public:
double quickMul(double x, int n) {
double ans = 1.0;
if(n == 0){
return 1.0;
}
ans *= quickMul(x, n/2);
return n%2==1?ans*ans*x:ans*ans;
}
double myPow(double x, int n){
if(n < 0){
if(n == INT_MIN) return 1.0/quickMul(x, -(n+1))*x;
else return 1.0/quickMul(x, -n);
}
return quickMul(x, n);
}
};
迭代算法
class Solution {
public:
double myPow(double x, int n) {
if(n==0) return 1.0;
bool is = true;
double ans = 1.0;
double result = x;
if(n < 1){
is = false;
if(n==INT_MIN){
ans = x;
n++;
}
n = -n;
}
while(n > 0){
ans = n%2==1 ? ans*result : ans;
result *= result;
n /= 2;
}
return is?ans:1.0/ans;
}
};