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 ...
随机推荐
- 【Selenium-WebDriver实战篇】selenium之使用Tess4J进行验证码图片识别内容
==================================================================================================== ...
- 【转】分布式事务,EventBus 解决方案:CAP【中文文档】
[转]分布式事务,EventBus 解决方案:CAP[中文文档] 最新文档地址:https://github.com/dotnetcore/CAP/wiki 前言 很多同学想对CAP的机制以及用法等想 ...
- docker拷贝宿主与容器中的文件
从容器里面拷文件到宿主机 语法:docker cp 容器名:要拷贝的文件在容器里面的路径 要拷贝到宿主机的相应路径 例子:容器名为ubuntu,要从容器里面拷贝的文件路为:/usr/local/tom ...
- Codeforces1114F Please, another Queries on Array?
题目链接:http://codeforces.com/problemset/problem/1114/F 题意:序列$a$,有两种操作,1 区间里的数同时乘上$x$ 2 求区间的积的欧拉函数 线段树好 ...
- 项目集成Spring Security
前言 之前写的 涂涂影院管理系统 这个 demo 是基于 shiro 来鉴权的,项目前后端分离后,显然集成 Spring Security 更加方便一些,毕竟,都用 Spring 了,权限管理当然 S ...
- 使用terraform v0.12 生成gitlab repo 创建部署tf 文件
以前写过一个使用模版引擎+ rest 接口的模式,生成tf 文件,v0.12 直接提供了方便的json 处理函数 我们可以直接结合http 以及templatefile providers 方便的 ...
- HTML5 Geolocation(地理定位)
一.背景 在HTML规范中,增加了获取用户地理信息的API,这样使得可以基于用户位置开发互联网应用,即基于位置服务 鉴于该特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的. Inter ...
- php7 configure: error: Cannot find OpenSSL's <evp.h> 问题解决
开始以为是没有安装openssl, openssl-devel,安装后发现还是提示这个错误,搜索了一下evp.h,这个文件也存在.GOOGLE 了一下,在stackoverflow,找到了答案,原来是 ...
- 洛谷 P4017 最大食物链计数 题解
P4017 最大食物链计数 题目背景 你知道食物链吗?Delia生物考试的时候,数食物链条数的题目全都错了,因为她总是重复数了几条或漏掉了几条.于是她来就来求助你,然而你也不会啊!写一个程序来帮帮她吧 ...
- SQL基础-连接表
一.连接表 1.SQL JOIN 忘记在哪保存的某位网友的图,先明白SQL JOIN, 2.关于笛卡尔积 笛卡尔积: 两个集合的乘积 重新建student表和teacher表: student表: C ...