算法第二章上机实践报告
一、实践题目
二分查找:输入n值(1<=n<=1000)、n个非降序排列的整数以及要查找的数x,使用二分查找算法查找x,输出x所在的下标(0~n-1)及比较次数。若x不存在,输出-1和比较次数。
输入格式:
输入共三行: 第一行是n值; 第二行是n个整数; 第三行是x值。
输出格式:
输出x所在的下标(0~n-1)及比较次数。若x不存在,输出-1和比较次数。
输入样例:
4
1 2 3 4
1
输出样例:
0
2
二、问题描述
在一个有序排列的一维数组中寻找一个数,输出这个数的下标以及过程中的比较次数。
三、算法描述
1 #include<iostream> 2 using namespace std; 3 4 int BinarySearch(int* a, int n,int x, int &com){ 5 int left = 0; 6 int right = n-1; 7 while(left <= right){ 8 int middle = (left + right) / 2; 9 if(x == a[middle]){ 10 com++; 11 return middle; 12 } 13 if(x > a[middle]){ 14 com++; 15 left = middle + 1; 16 } 17 else{ 18 com++; 19 right = middle-1; 20 } 21 } 22 return -1; 23 } 24 25 int main(){ 26 int a[1001]; 27 int n; 28 cin >> n; 29 for(int i=0; i<n; i++){ 30 cin >> a[i]; 31 } 32 int x; 33 cin >> x; 34 int com = 0; 35 int location = BinarySearch(a, n, x, com); 36 cout << location<< endl; 37 cout << com; 38 return 0; 39 }
该题核心算法是二分查找,它的基本思想是:将n个元素分成个数大致相同的两半,取a[n/2]与x作比较。如果x=a[n/2],则找到x,算法终止;如果x<a[n/2], 则只在数组a的左半部继续搜索;如果x>a[n/2], 则只在数组的右半部分继续搜索x。
其实这道题的主要部分与书上第17页的例题基本相同,只是多了一个输出比较次数,所以我们只需在原本的基础上增加一个用于统计次数的变量,并且考虑这个变量该如何返回输出。又因为一个函数只能返回一个值,我们用于返回下标,所以num选择使用引用的方法,直接改变主函数里的实参。
四、算法时间及空间复杂度分析
1、时间复杂度:
我们容易看到,每执行一次算法的while循环,待搜索数组的大小减小一半,循环体内运算需要O(1)时间。因此,在最好的情况下,也就是第一次循环,一次比较就找出了x,整个算法的时间复杂度为O(1);在最坏的情况下,也就是在最后才确定结果,while循环被执行了O(logn)次,整个算法的时间复杂度为O(logn).
2、空间复杂度:
因为整个过程中用到的辅助空间只有一个数组a,所以空间复杂度为O(1)。
五、心得体会(对本次实践收获及疑惑进行总结)
1、我们一开始用的是递归的方法,结果总是出错,连下标的输出都不正确,百思不得其解,然后我和小伙伴打开了书,发现我们将while循环用在了递归里......当时真的觉得自己是zhu。说到底,我们还是对于算法本身的理解不够到位,过于依赖书本,习惯了直接按照书上的代码去敲,却没有进一步的思考。这也给了我一定的警示—我需要有脱离书本独自将代码打出来的能力。
2、之后我们就选择了非递归的方法,为了简洁有效的输出num,我们想到了引用方式的传参,然而num的输出还是会出错,它总是比我们期望的要少1,我们还天真的在最后让它加上1输出。嗯,在dev里运行样例成功了。于是我们期待地将它放进了pta,嗯......失败了。于是我们又翻来覆去的找,发现是我们将num++放在了renturn的后面,导致结果出错。果然是细节决定成败。
3、其实一开始我觉得这道题还挺简单的,不就是在例题的基础上加一个变量来返回比较次数吗?然而现实狠狠地打了我一下,我们搞了很久很久......但是我回过头去看,我们犯的那些错误都是很基础的,反应过来后觉得我自己真的是蠢到哭。也让我更深刻地认识到理想和现实还是有很大差距的,在理解算法核心思想的同时,我更需要有将想法变成可实现的代码的能力,毕竟我们的最终目的还是期望打出可以解决问题的代码。而这种能力不是我光天天看书就可以获得的,我更需要脱离书本实际操作,在不断解决错误中提高自己的能力,就像这次,通过打代码,我对二分算法有了更深入的了解,虽然我以后可能还会犯与这两个类似的错误,但我相信我可以更快的发现并解决。
原文地址:https://www.cnblogs.com/WWYlaowu/p/11567993.html
- Spring思维导图,让Spring不再难懂(cache篇)
- 曲折的10g,11g中EM的安装配置过程(r4笔记第98天)
- Linux 学习记录 一(安装、基本文件操作).
- 实用的位运算应用(r4笔记第97天)
- 关于date格式的两个案例(r4笔记第96天)
- 【新技术分享】C++17 最新进展
- Ant + Jenkies +Tomcat 自动构建部署Web项目
- 博客项目Tale思维导图,让项目不再难懂
- 关于权限管理的实用脚本(r4笔记第94天)
- Ant学习笔记
- 清理session的小插曲(r4笔记第95天)
- CVE-2017-16943 Exim UAF漏洞分析
- Java泛型学习
- Jenkins修改管理员密码.
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 拓扑排序-HDU2647 Reward
- hadoop2.7.3源码解析之HA架构分析
- hadoop源码解析之hdfs内部结构分析
- 浙大版《C语言程序设计(第3版)》题目集 习题10-5 递归计算Ackermenn函数
- 浙大版《C语言程序设计(第3版)》题目集 习题10-6 递归求Fabonacci数列
- hadoop2.7.3源码解析之hdfs删除文件全流程分析h
- 二维树状数组-POJ 2155 Matrix
- 浙大版《C语言程序设计(第3版)》题目集 习题10-7 十进制转换二进制
- flink开发过程中遇到的问题集锦
- FLINK实战-使用CEP进行网站监控报警和报警恢复
- 浙大版《C语言程序设计(第3版)》题目集 习题10-8 递归实现顺序输出整数
- 浅谈DAO设计模式(示例)
- 浙大版《C语言程序设计(第3版)》题目集 习题11-1 输出月份英文名
- flink教程-flink 1.11 使用sql将流式数据写入hive
- flink实战-使用广播实现报警阈值动态更新