算法第二章上机实践报告

实践题目名称

7-2 二分法求函数的零点

问题描述

image

算法描述

解决这道题目,运用二分法。

点击查看代码
#include <bits/stdc++.h>
using namespace std;

double f(double x) {
 return pow(x, 5) - 15*pow(x, 4) + 85*pow(x, 3) - 225*pow(x, 2) + 274*x - 121;
}

double solve(double left, double right){
 double mid = (left + right) / 2;
 if(fabs(f(mid)) < 1e-7)
  return mid;
 if(f(mid) > 0)
  return solve(mid, right);
 else
  return solve(left, mid);
}

int main(){
 double root;
 root = solve(1.5, 2.4);
 cout << fixed << setprecision(6) << root;
 return 0;
}

1、首先由题目可以知道,这个函数在[1.5,2.4]之间的图像呈递减形式,在0的左边函数大于0,在0的右边函数小于0.


2、编写slove函数,用于二分递归。
①首先先设置一个 mid = (left + right) / 2,每次递归都取中间(二分),这里要注意的是,接下来判断mid为不为0不能直接用if(mid==0)判断,因为mid是浮点数,所以必须要用函数的变量为mid的时候的绝对值小于1e-7判断mid是否为零点,如果为0证明找到零点,直接返回mid值。
②如果mid不是零点,判断它是否大于0,若大于0,则证明零点在mid的左边,更新left,需要继续查找从mid开始左边的范围(即mid~right),小于0同理,查找右边,更新right。


3、四舍五入小数点到六位,要注意输出时加上格式设置。

算法时间及空间复杂度分析(要有分析过程)

时间复杂度

这道题中:
通过O(1)的操作(if比较、取中值等等),将规模为 n 的问题变成了 n/2 的问题。
即:T( n ) = T ( n / 2 ) + O ( 1 )
所以:T( n )= O(1)+ O(1)= O(logN)
在这道题目中N=0.9,所以是0(1)

空间复杂度

没有用到辅助空间单元存放元素,为O(1)

心得体会(对本次实践收获及疑惑进行总结)

1、感受到了二分法的厉害!代码又短效率又高!这道题的范围只是[1.5,2.4],所以不用二分可能也能过,但是如果范围特别大的话,还是需要二分来提高效率。

2、这道题目的边界设置比较简单,主要是注意判断浮点数为0的方式。在递归+1的时候也不用进行mid+1和mid-1的操作。

3、这道题目过后,能够更加熟练运用二分法解决问题。并且发现了二分和分治的不同,二分是不断递归缩小范围,分治是将问题分成很多个子问题,对每个子问题都要求解。

分治法的个人体会和思考

1、分治法要特别注意递归的细节。例如这次上机实验的第一题,有一段代码是更新left的时候mid要+1,但是更新right的时候mid不用-1,因为答案也有可能就是mid本身,就很容易出错。二分法不能说完全按照模板打,具体题目要具体分析。

2、分治法的确能大大提高运行效率。在做这次上机实验的第三题时,一开始我写了个暴力双重循环,运行没问题但是PTA会运行超时,运用了二分法重新做了之后就能顺利通过了。

3、如果一道很繁琐的题目,他的解可以分成很多个子问题的解,最后合并,而子问题又很好求解的话,就要考虑是不是能用分治法去解决问题,会大大提高效率!

posted @ 2021-09-30 16:42  yeyuunjia  阅读(54)  评论(0编辑  收藏  举报