C++刷题日记:Leetcode 50. Pow(x,n)

C++刷题日记:Leetcode 50 Pow x,n

  • 题目
  • 解析
  • 实现
    • 暴力求解 v1
    • 按位移动法 v2
    • 二分思想v3

题目

Leetcode 50. Pow(x,n)
实现 pow(x, n) ,即计算 x 的 n 次幂函数(x^n)
C++刷题日记:Leetcode 50. Pow(x,n)_第1张图片

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/powx-n
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解析

拿到手直接

class Solution {
public:
    double myPow(double x, int n) {
	return pow(x,n);
    }
};

调cmath里的pow方法。就AC了
C++刷题日记:Leetcode 50. Pow(x,n)_第2张图片
不过这道题本意应该是要自己写方法
最直接的思路仅仅考虑实现,通过次数循环控制x自乘即可。这是v1版本
考虑到大量的for费时又费力
想想这道题是要求幂次,可以通过二进制移位方式来实现。可以写出v2版本代码
再想想可以通过缩小规模来实现,这是v3代码

实现

暴力求解 v1

class Solution {
public:
    double myPow(double x, int n) {
	long long N=n;
	if(N<0){
		x=1/x;
		N=-N;
	}
	double ans=1;
	for(long long i=0;i<N;i++)ans*=x;
	return ans;
    }
};

时间复杂度O(n)
空间复杂度O(1)
C++刷题日记:Leetcode 50. Pow(x,n)_第3张图片
结果是没错,不过不出意外的,超出了时间限制。

按位移动法 v2

注意,起初的思路是通过对x进行按n进行移位操作,后来发现C++中的移位操作只能对int操作。也就是可以对整数实现pow,对带有小数的会失败。还是把代码放出来供参考

class Solution {
public:
    double myPow(double x, int n) {//失败,仅对整数可以实现求幂次,带小数结果错误
	if(n==0)return 1;
	if(n==1)return x;
	int res=(int)x;
	res<<=abs(n)-1;
	return n>0?(double)res:(1/(double)res);
    }

通过对计算次数减少,也就是对幂次n进行移位。可以大幅减少运算次数,并且成功AC。代码如下

class Solution {
public:
    double myPow(double x, int n) {
	if(n==0)return 1;
	if(n==1)return x;
	if(n==-1)return 1/x;
	if(n&1){
		return myPow(x*x,n>>1)*x;
	}
	return myPow(x*x,n>>1);
    }
};

C++刷题日记:Leetcode 50. Pow(x,n)_第4张图片

二分思想v3

采用分治法,通过二分法实现O(log n)的时空复杂度

class Solution {
public:
double f(double x,int n){
	if(n==0)return 1;
	double half=f(x,n/2);
	return n&1==1?half*half*x:half*half;
}
    double myPow(double x, int n) {
	if(n==0||x==1)return 1;
	long long N=n;
	return N>0 ? f(x,N): 1/ f(x,-N); 
	}
};

C++刷题日记:Leetcode 50. Pow(x,n)_第5张图片

迭代

妙在对幂转了2进制,从最后一位开始判断是否有做出贡献,如2^16次方。
如x^77次方,77的二进制形式对应了(1001101)中的每个1。
2^0=1
2^2=4
2^3=8
2^6=64
把这些幂次相加等于77
C++刷题日记:Leetcode 50. Pow(x,n)_第6张图片

这里来个例子,比如x=2,n=16。指数16可以拆分为2^4次方,二进制表示形式就是(10000),程序过程如下图所示
C++刷题日记:Leetcode 50. Pow(x,n)_第7张图片

class Solution {
public:
double ff(double x,long long n){
	double x_useful=x;
	double ans=1;
	while(n>0){
		if(n&1){
			//末位是1
			ans*=x_useful; 
		}
		x_useful*=x_useful;
		n/=2;
	}
	return ans;
}
    double myPow(double x, int n) {
    long long N=n;
	return N>=0? ff(x,N):1/ff(x,-N);
	}
};

C++刷题日记:Leetcode 50. Pow(x,n)_第8张图片
时间复杂度:O(logn)
空间复杂度:O(1)

你可能感兴趣的:(C++算法,leetcode,c++,算法)