class Solution {
public double myPow(double x, int n) {
double res = 1; // 保存结果
long y = n; // 取值
// 如果指数为负数,则取指数的绝对值,并将取底数的倒数
if (y < 0) {
y = -y;
x = 1 / x;
}
while (y > 0) {
// 按照二进制的方式,如果当前位为1,则乘以对应的x^n
if (y % 2 == 1) {
res *= x;
}
x = x * x;
y = y / 2; // y右移
}
return res;
}
}
class Solution {
public double myPow(double x, int n) {
double res = 1;
long y = n;
if(n < 0){
y = -y;
x = 1 / x;
}
while(y > 0){
if(y % 2 == 1){
res = res * x;
}
x = x * x;
y = y / 2;
}
return res;
}
}
【题解2】思路同题解1,位运算版本
class Solution {
public double myPow(double x, int n) {
// 【错误点1】不转换成long,会导致 n = -2147483648,(负数的绝对值是比正数要大1位的)
// 执行 n = -n 时,-2147483648 不能被直接取反,因为其绝对值超出了 int 类型的表示范围。结果,n 仍然是 -2147483648
long N=n;
if (N < 0) {
x = 1 / x;
N = -N;
}
// 6^7= 6^(1+2+4)=6^1*6^2*6^4
// 可以通过6^1-》6^2 -》 6^4 加快计算速度(无需计算到6^7)
// 问题变成了1,2,4如何获取到? 比如7的二进制是110
// 110 & 1 =0,说明最右边位是0;110右移1位,110>>1变成11,11&1=1,说明此时是1
double sum = 1;
double tmpt = x;
while (N != 0) {
if ((N & 1) == 1) {
sum = sum * tmpt;
}
N = N >> 1;
tmpt = tmpt * tmpt;
}
return sum;
}
}
错误点1:不转换成long,会导致 n = -2147483648,(负数的绝对值是比正数要大1位的)
执行 n = -n 时,-2147483648 不能被直接取反,因为其绝对值超出了 int 类型的表示范围。结果,n 仍然是 -2147483648
class Solution {
public double myPow(double x, int n) {
long N = n;
return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N);
}
public double quickMul(double x, long N) {
if (N == 0) {
return 1.0;
}
double y = quickMul(x, N / 2);
return N % 2 == 0 ? y * y : y * y * x;
}
}
class Solution {
public double myPow(double x, int n) {
if (x == 0.0f)
return 0.0d;
long b = n;
double ans = 1;
if (b < 0) {
x = 1 / x;
b = -b;
}
while (b > 0) {
if ((b & 1) == 1) {
ans *= x;
}
x *= x;
b >>= 1;
}
return ans;
}
}
class Solution {
public double myPow(double x, int n) {
double res = 1;
// 负数比正数多一个
long y = n;
if (y < 0) {
// 负数次幂
x = 1 / x;
y = -y;
}
while (y > 0) {
if (y % 2 == 1) {
res *= x;
}
x *= x;
y /= 2;
}
return res;
}
}
class Solution {
public double myPow(double x, int n) {
// 如果 n 为负数,转换为正数,且 x 转换为且倒数 1/x;当 n == Integer.MIN_VALUE 时,-n 会越界,所以将 n 先转换为 long 类型
long b = n;
double res = 1.0;
if (b < 0) {
b = -b;
x = 1 / x;
}
double tmp = x;
// 将 b 转换为二进制,每遇到 1 时,就进行乘法计算
while (b != 0) {
if ((b & 1) == 1) {
res *= tmp;
}
tmp *= tmp;
b = b >> 1;
}
return res;
}
}
共以下 11 个回答
时间复杂度O(logN), 空间复杂度O(1)
解题思路
– 常规思维
– 6^10= 6^(2+8)=6^26^8
– 可以通过6^1-》6^2 -》 6^4 加快计算速度(无需计算到6^7)
– 问题变成了2,8如何获取到?
– 比如10%2的余数是0,说明6^1不存在
– 5%2的余数是1,说明6^2存在(6^2=6^16^1);
– 2%2的余数是1,说明6^4存在(6^4=6^26^2)
总结:【余数是否为1,表示是否要去sum里面;但是6^1-》6^2-》6^4的递增过程不收到余数是否为1的影响】
– 位运算思维
– 问题变成了2,8如何获取到? 比如10的二进制是1010【】
– 1010 & 1 =0,说明最右边位是0;
– 1010右移1位(1010>>1变成101),101&1=1,说明此时是1
– 101右移1位(101>>1变成10),10&1=0,说明此时是0
– 10右移1位(10>>1变成1),1&1=1,说明此时是1
总结:【余数是否为1,用 n &1 是否等于1去完成;/2 使用 n>>1去完成 】
【题解1】纯思路,非位运算版本
【题解2】思路同题解1,位运算版本
执行 n = -n 时,-2147483648 不能被直接取反,因为其绝对值超出了 int 类型的表示范围。结果,n 仍然是 -2147483648
class Solution {
public double myPow(double x, int n) {
long N=n;
if (N < 0) {
N=-N;
x=1/x;
}
double res=1.0;
while(N>0){
if(N%21){
res=resx;
}
x=xx;
N=N/2;
}
return res;
}
}\
时间复杂度:O(n)
空间复杂度:O(1)
思路:参考力扣题解 使用 快速幂 计算
将n保存为long防止负数时数值溢出。
时间复杂度O(logN),空间复杂度O(1)。
时间复杂度O(logN)
空间复杂度O(1)
class Solution {
public double myPow(double x, int n) {
long exp = n; // 转换为 long,避免溢出
if (exp < 0) {
x = 1 / x;
exp = -exp;
}
}
int类型溢出问题
递归解法,未用位运算
Ologn Ologn
位运算解法 空间复杂度低
Ologn o1
思路:位运算,注意 n 的取值范围。
时间复杂度:O(logn)
空间复杂度:O(1)