python基础篇(五)
PYTHON基础篇(五)
- 算法初识
- 什么是算法
- 二分查找算法
♣一:算法初识
A:什么是算法
根据人们长时间接触以来,发现计算机在计算某些一些简单的数据的时候会表现的比较笨拙,而这些数据的计算会消耗大量计算机资源,而且耗时,这个时候就有人对这类计算编写了一些策略,这些策略就是算法。这些策略会加快数据计算时间,大大减少计算机的资源消耗。
在长时间人们编写代码的工作中,一些优秀的算法就被流传下来,但是不是所有的算法都能实现目的一步到位的工作,它只能减少你的代码,提高工作效率,随着知识的不断积累,你会发现有更好的办法来完成算法所完成的事情。
B:二分查找算法
当有一个文件,文件里面都是数字,要写一段代码查找用户需要的数字在什么位置。之前的知识我们可能会使用循环去读取这个文件的每一行并最终找到这个数字所在的位置,此类方法可以达到目的,但是消耗了很多不必要的时间和资源。
这个其实也都想到了就是算法,上面的问题思路是这样的,我们首先把这个文件中数据的中间值取出来,让用户需要查找的数据这个这个中间值做比对,如果用户输入的数字大于这个中间值,那么我就往后找,再取一次这个中间值,再做比较,这样以此类推直到找到这个数字,并取出这个数字所在的位置即可。
- #二分查找算法:
- #版本1:
- l = [2,4,5,6,8,13,22,24,44,56,66,67,68,88,89,90,99]
- def find(l,tag): #tag是用户输入要查找大数字
- half_tag = len(l)//2 #取一半的下标,此处要使用整除,防止除不尽的情况 #假如中间值是44
- if l[half_tag] < tag: #用取一半列表再去哥用户要找的数字比对
- num_l = l[half_tag+1 :] #如果用户输入的数字大于一半的下标,那么就从44后面找,这个位置要加1,是因为44在大于的时候已经比对过了,要从56开始比对
- #num_l = l[half_tag+1 :] #把上面切掉的一半数据赋予新的变量名。
- find(num_l,tag) #从上面新变量里面再去找,用户输入的是不是大于或者小于列表,一直重复下去,直到找到数字取到下标
- elif l[half_tag] > tag:
- num_l = l[:half_tag] #如果小于,就从24往前找,这个时候就不用加1,这个是切片的顾头不顾尾的原则
- #half_tag = len(num_l)//2
- find(num_l,tag)
- else:
- print('找到了!',half_tag,l[half_tag]) #最后一种情况就是找到了,那就直接打印即可。
- find(l,66)
二分查找算法版本1
从上面的版本1,我们初步的把整个我们想实现目的的大致过程给写了出来,但是会发现有问题,我们要取的数字下标在l列表里面,结果出来的下标是1,这个和实际的情况不相符,我们要找的数字66是在l列表里面,不是在num_l新列表里面,接下里进行优化。
- l = [2,4,5,6,8,13,22,24,44,56,66,67,68,88,89,90,99]
- def find(l,tag,start=0,end=len(l)): #既然上面我们发现错误点是在新列表里面找的,那么我们需要让代码不断的从原始的l列表里面找。
- #那么就需要定义一个开始start和结束end,让下面的代码在l列表里面调整start和end的位置即可。
- #half_tag=len(l)//2 如果还是使用len(l)//2的话,half_tag就会是一个新的列表,那么还是没有解决从l列表找的问题。
- half_tag = (end - start)//2 + start #例如end表99的位置是20,start的值10,那么就是20-10/2=5,下标是5就不对了。
- #下标是5就从l表前面去找了,所以要加一个start,这样取的就是l的中间值了。
- if l[half_tag] < tag:
- find(l,tag,start=half_tag+1,end=end) #当取出一半的列表之后,find读取到用户在l列表里面找,开始的位置是上面比较之后的结果
- #结束位置就是l列表结束的位置。
- elif l[half_tag] > tag:
- find(l,tag,start=start,end=half_tag-1)
- else:
- print('找到了!',half_tag,tag)
- find(l,66)
二分查找算法版本2
版本2里面我们已经解决了每次从新列表取的bug了,但是还是存在问题,1:end这个参数有问题,2:返回值的问题,我们虽然取到了结果,但是这个结果不能用于其它代码去调用,功能单一了,3:要是用户找的数字不再l列表里面怎么办。
- l = [2,4,5,6,8,13,22,24,44,56,66,67,68,88,89,90,99] #问题1:如果l列表在函数代码下面出现,find函数就会出现问题。
- def find(l,tag,start=0,end=None): #要解决上面的问题,需要把end变成默认参数
- end = len(l) if end is None else end #在通过三元运算符来返回end,当end是空的时候就返回len(l),否则返回end(用户传过来的指)
- half_tag = (end - start)//2 + start
- if start <= end: #在find函数内部不断在执行的时候,会不断给start,end传输新的指,那么如果函数里面出现开始的指大于或者等于结束指了。
- #那么理论上就出现错误了,说明该数字就不存在表里面。
- if l[half_tag] < tag:
- find(l,tag,start=half_tag+1,end=end)
- elif l[half_tag] > tag:
- find(l,tag,start=start,end=half_tag-1)
- else:
- print('找到了!',half_tag,tag)
- else:
- print('找不到该数字') #当开始大于等于结束指了,就直接报错找不到
- find(l,23)
- #问题2:要是要找的数字不在l列表里面,find函数肯定会报错
- # l = [2,4,5,6,8,13,22,24,44,56,66,67,68,88,89,90,99]
- # def find(l,tag,start=0,end=None):
- # end = len(l) if end is None else end
- # half_tag = (end - start)//2 + start
- # if start <= end:
- # if l[half_tag] < tag:
- # find(l,tag,start=half_tag+1,end=end)
- # elif l[half_tag] > tag:
- # find(l,tag,start=start,end=half_tag-1)
- # else:
- # return half_tag #如果我在此处使用return,他是直接把返回值给到了上一级的find,也就是判断l>tag地方的find,或者l<tag地方的find.
- # #因为函数内部在调用find,而这个find是不能接受这个返回值的,也就等于函数在上面的if地方就结束了。
- # #函数在if的位置结束了,也就不会走到else的地方了,那么加在此处的return就return的是一个空,自然得到的结果就是none了
- # else:
- # print('找不到该数字')
- # find(l,23)
- # #问题3:被查找到的数字不能被二次调用。
- l = [2,4,5,6,8,13,22,24,44,56,66,67,68,88,89,90,99]
- def find(l,tag,start=0,end=None):
- end = len(l) if end is None else end
- half_tag = (end - start)//2 + start
- if start <= end:
- if l[half_tag] < tag:
- return find(l,tag,start=half_tag+1,end=end)
- elif l[half_tag] > tag:
- return find(l,tag,start=start,end=half_tag-1)
- else:
- return half_tag
- else:
- return '找不到该数字' #上面既然会出现大于,小于,等于,找不到四种情况,每种情况都有可能返回了指接收不了,那么我们
- #每次调用的指都返回回去,这样最外层的find就不会中断继续执行了,整个find函数就可以继续执行了
- ret=find(l,23)
- print(ret)
- #问题3:被查找到的数字不能被二次调用。
二分查找算法版本3
上面的二分查找算法是使用递归函数来完成的,经过上面的验证,我们队递归函数有又新的理解。
1:只要写递归函数,一定就需要结束的条件,而这个结束的条件就是你知道结果就应该要结束掉了;
2:返回值这个地方,需要看返回操作是在递归到第几层的时候发生的,返回了给了谁,如果这个返回值不是返回到最外层函数,调用的层面是接收不到的,所以说这个返回值一定要返回到最外层函数;
3:在实际的场景中,只要能用算法解决的事情,必定多多少少会用到递归函数,而且所以语言都有递归的概念;
4:递归函数,最好是从结果往前推。
- def fib(x):
- if x==1 or x==2:
- return 1
- return fib(x-1)+fib(x-2)
- fib1=fib(6)
- print(fib1)
斐波拉契递归函数
上面的斐波拉契函数正常我们要查询数字比较小的,很快就能查出来,但是要是查询80或者100等,就会发现很慢,这个是因为return fib(x-1) + fib(x-2),这里面调用了两次fib函数,这会导致函数执行效率大打折扣,从表面我们看到fib(x-1)就是fib(5),fib(x-2)就是fib(4),但是程序在执行的时候,是要先算出fib(5)=fib(x-1)也就是fib(4),fib(4)=fib(x-1)也就是fib(3),就这样一层层的算到初始值1+1,如果是50,等于fib两边的数字先要分别以一种金字塔的形式分别算下去,这个就是导致程序执行慢的根本原因,所以说在递归函数,千万不要在内部调用多次。
- def fib(x):
- if x==2:
- return 1,1
- else:
- a,b=fib(x-1) #这个else里面的代码就是解决上面fib调用多次导致效率低的关键,因为你在计算3的时候你肯定知道是1+2,那么在fib计算一次之后
- #我就计算的数据赋值给两个变量。
- return b,a+b#上面得到的两个值为了不要重复计算我下一个指,我就把上一次计算的指返回去一个,例如:用户找4,那么就是fib(1)+fib(2),
- #用户在查询5的时候,我已经把fib(4)和fib(2)+fib(3)准备好了,且返回给了上一层的a,b两个变量,等于a,b重新被赋值了。
- print(fib(3))
- 解决查询的值会显示两位的问题
- def fib(x,l=[0]):
- l[0]+=1
- if x==1 or x==2:
- l[0]-=1
- return 1,1
- else:
- a,b=fib(x-1)
- l[0]-=1
- if l[0]==0:
- return a+b
- return b,a+b
- print(fib(10))
斐波拉契函数版本2
- def fac(x):
- if x==1:
- return 1
- return x*fac(x-1)
- print(fac(5))
阶乘函数
5:递归函数一定要考虑到最大递归的998的问题,在之前的文章中有一定的介绍。
python基础篇(五)的更多相关文章
- Python基础篇(五)
bool用于判断布尔值的结果是True还是False >>> bool("a") True >>> bool(3) True >>& ...
- Python基础篇(五)_文件和数据格式化
Python基础篇_文件和数据格式化 文件的使用:文件打开.关闭.读写 文件打开:通过open()函数打开文件,并返回一个操作文件的变量. 使用语法:<变量名> = (<文件路径以及 ...
- python基础篇(六)
PYTHON基础篇(六) 正则模块re A:正则表达式和re模块案例 B:re模块的内置方法 时间模块time A:时间模块的三种表示方式 B:时间模块的相互转换 随机数模块random A:随机数模 ...
- python基础篇(一)
PYTHON基础篇(一) 变量 赋值 输入,输出和导入 A:输入 B:输出 C:导入 运算符 A:算数运算符 B:比较运算符 C:赋值运算符 D:位运算符 E:逻辑运算符 F:成员运算符 G:身份运算 ...
- python基础篇(二)
PYTHON基础篇(二) if:else,缩进 A:if的基础格式和缩进 B:循环判断 C:range()函数和len()函数 D:break,contiue和pass语句 for,while循环 函 ...
- python基础篇(三)
PYTHON基础篇(三) 装饰器 A:初识装饰器 B:装饰器的原则 C:装饰器语法糖 D:装饰带参数函数的装饰器 E:装饰器的固定模式 装饰器的进阶 A:装饰器的wraps方法 B:带参数的装饰器 C ...
- python基础篇(文件操作)
Python基础篇(文件操作) 一.初始文件操作 使用python来读写文件是非常简单的操作. 我们使用open()函数来打开一个文件, 获取到文件句柄. 然后通过文件句柄就可以进行各种各样的操作了. ...
- 面试题之第一部分(Python基础篇) 80题
第一部分(python基础篇)80题 为什么学习Python?==*== # 1. python应用于很多领域,比如后端,前端,爬虫,机器学习(人工智能)等方面,几乎能涵盖各个开发语言的领域,同时它相 ...
- python基础篇-day1
python基础篇 python是由C语言写的: pass 占位符: del,python中全局的功能,删除内存中的数据: 变量赋值的方法: user,pass = 'freddy','freddy1 ...
随机推荐
- $().on()的知识点
事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签. 假设一个元素div,它有一个下级元素p.<div> <p>元素</p></ ...
- Tips on Blind Source Separation
盲源分离是指在不知道源信号和信道传输参数的情况下,根据输入信号的统计特性,仅由观测信号恢复出源信号各个独立成分的过程.盲源分离研究的信号模型主要有三种:线性混合模型.卷积混合模型和非线性混合模型. 1 ...
- c++ socket发送数据时,sendData = char * string 导致的乱码问题
解决方法:将string 通过copy函数复制到某个char[] 1. string res =“xxx”; char arr[100]; int len = res.copy(arr, 100); ...
- BZOJ 4477: [Jsoi2015]字符串树 可持久化trie树
这个是真——可持久化字典树..... code: #include <bits/stdc++.h> #define N 100006 #define setIO(s) freopen(s& ...
- Xamarin.Forms 开发热加载利器 HotReload 推荐
https://github.com/AndreiMisiukevich/HotReload
- Python各种扩展名(py, pyc, pyw, pyo, pyd)区别
扩展名 在写Python程序时我们常见的扩展名是py, pyc,其实还有其他几种扩展名.下面是几种扩展名的用法. py py就是最基本的源码扩展名 pyw pyw是另一种源码扩展名,跟py唯一的区别是 ...
- 【BIRT】汉化设计器
点击下面文字即可下载汉化包 birt汉化_plugins.rar 下载完成之后,解压: 将上述文件copy到目录../eclipse/plugins/下即可 文件复制后,重新启动eclipse,则已经 ...
- [开源] FreeSql.AdminLTE.Tools 根据实体类生成后台管理代码
前言 FreeSql 发布至今已经有9个月,功能渐渐完善,自身的生态也逐步形成,早在几个月前写过一篇文章<ORM 开发环境之利器:MVC 中间件 FreeSql.AdminLTE>,您可以 ...
- Linux系统学习(二)一Linux基本操作
一.Linux的目录结构 1.1 Linux的目录结构图 1.2 目录内容 /:这就是根目录.对你的电脑来说,有且只有一个根目录.所有的东西,我是说所有的东西都是从这里开始.举个例子:当你在终端里输入 ...
- [源码分析]LinkedHashMap
一个键有序的 HashMap 可以将 LinkedHashMap 理解为 LinkList + HashMap,所以研究LinkedHashMap之前要先看HashMap代码.这里不再赘述.其实L ...