【leetcode 分治法】Pow(x, n)与Sqrt(x)函数的实现
来源:互联网 发布:博罗网络问政平台 编辑:程序博客网 时间:2024/04/29 07:08
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Pow(x,n)
1、分析
函数原型 double pow(double x, int n) ,实现求x的n次方
有一点需要注意:
int 类型范围 -2147483648~2147483647
当n=-2147483648,则-n=2147483648超出2147483647,结果-n仍然是-2147483648,所以这个情况应该单独处理。
int 类型范围 -2147483648~2147483647
当n=-2147483648,则-n=2147483648超出2147483647,结果-n仍然是-2147483648,所以这个情况应该单独处理。
也可以用机器码来解释这一个知识点:-2147483648的机器码为1000...0000(32位),实现取负:即机器码各位取反最后加1,得到的还是100....000。
这也是第下面代码中 if(n<0 && n!=INT_MIN) return 1.0/pow(x,-n) 为什么这样写的原因,如果写成if(n<0) return 1.0/pow(x,-n) 则会造成死循环
2、正解代码
分治法
<span style="font-size:18px;">double pow(double x, int n) { if(n<0 && n!=INT_MIN) return 1.0/pow(x,-n); else if(n==INT_MIN) {double val=pow(x,-(n/2)); return 1.0/val*val;} else if(n==0) return 1.0; else if(n%2==1) {double val=pow(x,(n-1)/2);return x*val*val; } else {double val=pow(x,n/2);return val*val;} }</span>
3、误解代码
下面的代码超时,因为:
pow(x,n/2)*pow(x,n/2)实际上计算了两次pow(x,n/2),但是正确的算法应该是计算出pow(x,n/2)后,赋给val,然后val*val,只计算一次pow(x,n/2)。下面的程序每一处都是pow()*pow(),这样一来跟x*x*x*x....一个一个乘没什么不同。
pow(x,n/2)*pow(x,n/2)实际上计算了两次pow(x,n/2),但是正确的算法应该是计算出pow(x,n/2)后,赋给val,然后val*val,只计算一次pow(x,n/2)。下面的程序每一处都是pow()*pow(),这样一来跟x*x*x*x....一个一个乘没什么不同。
<span style="font-size:18px;">double pow(double x, int n) { if(n<0 && n!=INT_MIN) return 1.0/pow(x,-n); else if(n==INT_MIN) return 1.0/(pow(x,-(n/2))*pow(x,-(n/2))); else if(n==0) return 1.0; else if(n%2==1) return x*pow(x,(n-1)/2)*pow(x,(n-1)/2); else return pow(x,n/2)*pow(x,n/2); </span>
Sqrt(x)
1、分析
函数原型 int sqrt(int x),实现求x的平方根。
几点注意:
#1 math头文件里的是double sqrt(double)等三种版本,leetcode上要实现的是int sqrt(int x),还是不同的
#2 int sqrt(int x)结果是向下取整的,比如sqrt(10)等于3,故我们要寻找的是1~x中最后一个满足val*val<x的那个数
#3 用二分查找法(先参见下面代码)
取1~x的中点mid,若mid*mid>x,那么根应该在1~mid-1之间,如果mid*mid<x,那么根应该在mid+1~x之间,若mid*mid==x则直接输出mid;
当然,在果mid*mid<x的情况下,根可能就是mid,但是我们仍然假设根在mid+1~x之间,程序运行下去会发现,mid+1~x的所有数的平方都大于x,最后while退出时first、last都等于mid+1,故while退出要处理,这就是if语句的一个作用
#4 考虑溢出问题
因为mid为int类型,所以mid*mid是有可能溢出的,应该声明为long long类型。
如果限定只能用int类型,那么可以将mid*mid<x 写成 mid<x/mid ,这样肯定不会溢出
2、代码
分治法,二分查找
class Solution {public: int sqrt(int x) { //x不会小于0 if(x==0) return 0; long long int first=1,last=x; while(first<last){ long long int mid=(first+last)/2; if(mid*mid<x) first=mid+1; //long long类型与int类型比较,int被暂时当作long long? else if(mid*mid>x) last=mid-1; else return mid; } if(first*first>x) return first-1; else return first; }};
1 0
- 【leetcode 分治法】Pow(x, n)与Sqrt(x)函数的实现
- Leetcode的Pow(x, n) 与 sqrt(x)
- 分治法实现pow(x,n)函数的功能
- [leetcode]Pow(x, n)&&Sqrt(x)
- [leetcode] 【分治法】 50. Pow(x, n)
- LeetCode Pow(x,n)(分治法)
- [leetCode] Pow(x,n)(分治)
- Leetcode 50. Pow(x, n) & 69. Sqrt(x)
- LeetCode.50(69) Pow(x,n)&&Sqrt(x)
- LeetCode 之 Pow(x, n)(分治法)
- [算法作业][LeetCode] 50. Pow(x, n) -- 分治法
- pow(x,n)的实现
- LeetCode: Pow(x, n)
- LeetCode Pow(x,n)
- [Leetcode] Pow(x, n)
- LeetCode: Pow(x, n)
- Leetcode: Pow(x,n)
- [LeetCode] Pow(x, n)
- Android4.4 Framework分析——PackageManangerService的启动过程
- 编程之美 1.4 买书问题
- 法第四十的发生的发生的范德萨发的说法
- (C)static关键字
- 小编程题之(3n+1)卡拉兹猜想
- 【leetcode 分治法】Pow(x, n)与Sqrt(x)函数的实现
- puTTY与SecureCRT的比较
- 利用jquery写的无限弹出移动窗口,仿桌面窗口移动,原理很简单
- Linux 下 增加修改删除 服务
- 和规范的规范的鬼地方
- OEE系统
- LeetCode OJ 之 3Sum (三个数的和)
- PS知识总结
- 编程之美 1.6 饮料供应