【leetcode 分治法】Pow(x, n)与Sqrt(x)函数的实现

</pre>Pow(x, n)</h1><h1><span style="color:#3333ff;">1、分析</span></h1><div><span style="font-size:18px;">函数原型double pow(double x, int n),实现求x的n次方。</span></div><div><span style="font-size:18px;"></span></div><div><span style="font-size:18px;">有一点需要注意:int n类型范围 -2147483648~2147483647当n=-2147483648,则-n=2147483648超出2147483647,结果仍然是-2147483648,所以应该单独处理。</span></div><div><span style="font-size:18px;">也可以用机器码来解释这一个知识点:-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) 则会造成死循环</span></div><h1><span style="color:#3333ff;">2、正解代码</span></h1><div><span style="font-size:18px;">分治法</span></div><div><pre name="code" class="cpp"><span style="font-size:18px;">class Solution {
public:
    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....一个一个乘没什么不同。

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);    

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、代码

分治法,二分查找

<span style="font-size:18px;">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;

    }
};</span>
时间: 2024-12-06 10:03:14

【leetcode 分治法】Pow(x, n)与Sqrt(x)函数的实现的相关文章

LeetCode 240. 搜索二维矩阵 II (C#实现)——二分查找,分治法

问题:https://leetcode-cn.com/problems/search-a-2d-matrix-ii/ 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target.该矩阵具有以下特性: 每行的元素从左到右升序排列. 每列的元素从上到下升序排列. 示例: 现有矩阵 matrix 如下: [ [1, 4, 7, 11, 15], [2, 5, 8, 12, 19], [3, 6, 9, 16, 22], [10, 13, 14, 17, 24], [18,

LeetCode刷题总结-双指针、位运算和分治法篇

本文总结LeetCode上有关双指针.位运算和分治法的算法题,推荐刷题总数14道.具体考点分析如下图: 一.双指针 1.字符串和数组问题 题号:424. 替换后的最长重复字符,难度中等 题号:828. 独特字符串,难度困难 题号:923. 三数之和的多种可能,难度中等 2.实际场景应用问题 题号:826. 安排工作以达到最大收益,难度中等 3.元素对问题 题号:986. 区间列表的交集,难度中等 二.位运算 1.字符串和数组问题 题号:137. 只出现一次的数字 II,难度中等 题号:318.

Leetcode 240 Search a 2D Matrix II (二分法和分治法解决有序二维数组查找)

1.问题描述 写一个高效的算法,从一个m×n的整数矩阵中查找出给定的值,矩阵具有如下特点: 每一行从左到右递增. 每一列从上到下递增. 2. 方法与思路 2.1 二分查找法 根据矩阵的特征很容易想到二分法,但是这是一个二维的矩阵,如何将问题转化为一维是关键.实际上我们可以根据矩阵的第一列确定值可能所在的行的范围(limu,limd),其中limu=0,使得matrix[0][0]≤matrix[i][0]≤matrix[limd][0],i∈[0,limd].而确定limd的值可以使用二分法.

leetcode 23. Merge k Sorted Lists(堆||分治法)

Merge k sorted linked lists and return it as one sorted list. 题意:把k个已经排好序的链表整合到一个链表中,并且这个链表是排了序的. 题解:这是一道经典好题,值得仔细一说. 有两种方法,假设每个链表的平均长度是n,那么这两种方法的时间复杂度都是O(nklogk). 方法一: 基本思路是:把k个链表开头的值排个序,每次取最小的一个值放到答案链表中,这次取完之后更新这个值为它后面的一个值.接着这么取一直到全部取完.那么每次更新之后怎么对当

分治法-最近距离问题Java实现

分治算法,有很多典型的问题,如最近点问题.线性选择问题.整数划分问题.大整数成绩问题.棋盘覆盖问题.循环赛日程表.二分搜索.Strassen矩阵乘法.汉诺塔等.准备花些时间逐个解决这些问题,并用Java实现,从最近点问题开始.网上找到一些代码,标题如"java 用蛮力法和分治法求解最近对有关问题",虽然体现了分治,但划分不够彻底,因此我重新对其进行了实现. 一.基本思想及策略: 首先,说说分治的思想.分治, "分而治之",就是把一个复杂的问题分成两个或更多的相同或相

HDU ACM 1007 Quoit Design 分治法求最近点对

题意:给n个点的坐标,求距离最近的一对点之间距离的一半. 分析:分治法求最近点对. #include<iostream> #include<algorithm> #include<cmath> using namespace std; #define N 100005 double min(double a,double b) { return a<b?a:b; } struct POINT { double x,y; }; POINT point[N],*px[

【算法】凸包问题--分治法

凸包问题--分治法 求能够完全包含平面上n个给定点的凸多边形. 示例: 一.分治法: (一)算法思路: (这里所说的直线都是有向直线的.) 将数组升序排序,若x轴坐标相同,按照y轴坐标升序排序. 最左边的点p1和最右边的点p_n一定是该集合凸包的顶点.该直线将点分为两个集合,上包为S1,下包为S2.在p1 p_n线上的点不可能是凸包的顶点,所以不用考虑. 在上包S1中,找到p_max(距离直线p1p_n最远距离的点),若有两个距离同样远的点,取∠p_max p1 p_n最大的那个点(即△p_ma

分治法(二)

参考  <算法设计与分析> 第四章 分治法     Anany Levitin著  翻译版   清华大学出版社 在上一篇文章中,介绍了分治策略的思想,主定理,以及几个用分治策略的经典案例.这一篇文章将继续探讨分治算法的其他应用,包括大整数乘法和Strassen矩阵乘法,最近点对问题和凸包问题这4个算法,一般来说常规的数据结构教程上不包括这些内容. --------------------------------------------------------------------------

分治法二(平面最近点对)

上篇文章介绍了分治法的概念和基本解题步骤,并附加了一个例题帮助大家了解分治法的基本思想,在这篇文章中,我将对分治法的另一个经典问题进行分析,希望我的文章能够将今天的主题解释清楚.接下来我将用三种不同的方法求解"平面最近点对"问题. 问题描述:在一个平面上随机分布着 n 个点,现给定 n 个点的坐标,要求给出最近的两个点之间的距离. 方法一:原始方法 题目要求求出最近的两点之间的距离,先整理一下已知的线索:首先点的总个数为 n :其次已知 n 个点的坐标.掌握了每个点的坐标,就相当于间接