python侯先生爬楼梯问题_python的算法

一、复习:

递归的两个特点:

1、调用自身。

2、结束条件。

1 1.deffunc1(x)2 print(x)3 func1(x-1)4

5

6 2.deffunc2(x)7 if x>0:8 print(x)9 func2(x+1)10

11

12 3.deffunc3(x)13 if x>0:14 print(x)15 func3(x-1)16

17

18 4.deffunc4(x)19 if x>0:20 func4(x-1)21 print(x)

看上列代码如果是func1跟func2就是无限循环,没有合理的结束条件。func3跟func4就是有合理条件,可以循环结束。

ps:但是func3跟func4虽然都没问题。但是print 的方式并不同,func3输出5.3.2.1。但是func4的输出结果是1.2.3.4.5 因为他每次循环是没有走print就进入了下一个循环 之中,往外出的时候才会进行打印。

二、时间复杂度

类比生活中的一些事件,估计时间:

1.眨一下眼            一瞬间/几毫秒

2.口算“29+68”             几秒

3.烧一壶水            几分钟

4.睡一觉             几小时

5.完成一个项目          几天/几星期/几个月

6.飞船从地铁飞出太阳系      几年

时间复杂度的表示方式

1 print('Hello World')2 print('Hello Python')3 print('Hello Algorithm')4 #用时间复杂度来讲是O(1)

5

6 for i inrange(n):7 print('Hello World')8 for i inrange(n):9 print('Hello World')10 #用时间复杂度来讲是O(n²)

11

12 for i inrange(n):13 for i inrange(n):14 print('Hello World')15 #用时间复杂度来讲是O(n²)

16

17 while n > 1:18 print(n)19 n = n // 2

20 #用时间复杂度来讲是O(logn)

时间复杂度-小结:

1.时间复杂度是用来估计算法运行事假你的一个式子(单位)。

2.一般来说,时间复杂度高的算法比复杂度低的算法慢。

3.常见的时间复杂度(按效率排序)

O(1)

4.不常见的时间复杂度(看看就好)

O(n!)  O(2^n)  O(n^n)

5.如何一眼判断时间复杂度?

循环减半的过程---O(logn)

几次循环就是n的几次方的复杂度

三、空间复杂度

1.空间复杂度:用来评估算法内存占用大小的一个式子

2.“空间换时间”

四、列表查找:从列表中查找指定元素

输入:列表、待查找元素

输出:元素下标或未查到元素

顺序查找:

从列表第一个元素开始,顺序进行搜索,直到找到为止。

1 defordinary_lookup(number):2 dict = range(1000)3 for i indict:4 if i ==number:5 print(i)6 break

7 ordinary_lookup(200)

二分查找

从有序列表的候选区data[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半。

1 importtime,random2

3 defcal_time(func):4 def wrapper(*args,**kwargs):5 ti =time.time()6 x = func(*args,**kwargs)7 ti2 =time.time()8 print('time cost:',func.__name__,ti2-ti)9 returnx10 returnwrapper11

12 @cal_time13 defbin_search(data_set,val):14 low =015 high = len(data_set) - 1

16 while low <=high:17 mid = (low + high)//2

18 if data_set[mid] ==val:19 returnmid20 elif data_set[mid] <21 low="mid">

22 else:23 high = mid - 1

24 return

25

26

27 def_binary_search(dataset, find_num):28 if len(dataset) > 1:29 mid = int(len(dataset) / 2)30 if dataset[mid] == find_num: #find it

31 #print("找到数字", dataset[mid])

32 pass

33 elif dataset[mid] > find_num: #找的数在mid左面

34 #print("\033[31;1m找的数在mid[%s]左面\033[0m" % dataset[mid])

35 returnbinary_search(dataset[0:mid], find_num)36 else: #找的数在mid右面

37 #print("\033[32;1m找的数在mid[%s]右面\033[0m" % dataset[mid])

38 return binary_search(dataset[mid + 1:], find_num)39 else:40 if dataset[0] == find_num: #find it

41 #print("找到数字啦", dataset[0])

42 pass

43 else:44 pass

45 #print("没的分了,要找的数字[%s]不在列表里" % find_num)

46

47 @cal_time48 defbinary_search(data_set, val):49 return_binary_search(data_set, val)50 #不要在递归里面直接加装饰器会无限调用。

51 #循环要比递归有效率

52 #切片是一个特别耗费时间的操作

53

54 data = list(range(100000))55 bin_search(data,152)56 binary_search(data, 152)

练习:使用二分查找法,进行查找相应的id号码。

1 defrandom_list(n):2 ids = list(range(1001,1001+n))3 result =[]4 a1 = ['周','x','x,'x','x','x','x','x','x']

5 a2 = ['杰','x','x','x','x','x','x','x']6 a3 = ['伦','x','','','x','x','x','x','x','x']7 for i inrange(n):8 age = random.randint(18,60)9 id =ids[i]10 name = random.choice(a1)+random.choice(a2)+random.choice(a3)11 name_dict = {'id':id,'name':name,'age':age}12 result.append(name_dict)13

14 returnresult15

16 #用于生成一个关于姓名的列表包含字典

17

18 defbin_search(val):19 data_set = random_list(10000)20 low =021 high = len(data_set) - 1

22 while low <=high:23 mid = (low + high)//2

24 if data_set[mid]['id'] ==val:25 returnmid26 elif data_set[mid]['id'] <27 low="mid">

28 else:29 high = mid - 1

30 return

31 print(bin_search(1160))32

33 #用二分查找进行查找生成列表内的id号在第几个

各种排序演示网站http://www.atool.org/sort.php

五、列表排序:将无序列表变为有序列表

1.应用场景:

各种榜单

各种表格

给二分排序用

给其他算法用

2.使用方式

输入:无序列表

输出:有序列表

分为生序和降序

3.排序low b 三人组:

冒泡排序

选择排序

插入排序

4.快速排序

5.排序NB两人组:

堆排序

归并排序

6.什么人用的排序

基数排序

希尔排序

桶排序

冒泡排序

首先,列表每两个相邻的数,如果前边的比后面的打,那么交换这两个数...

需要记住两个概念,趟,无序区。

时间复杂度:O(n²)

1 def bubble_sort(li):2 for i in range(len(li)-1): #记录多少趟3 flag =False4 for j in range(0,len(li)-i-1): #交换了多少次5 if li[j] > li[j+1]:6 li[j],li[j+1] = li[j+1],li[j] #交换7 flag =True8 ifnot flag:9 break

选择排序

一趟便利记录最小的数,放到第一个位置;

再一趟遍历记录剩余列表中最小的数,继续放置;

需要记住两个概念,无序区,最小数的位置。

时间复杂度:O(n²)

1 defselect_sort(li):2 for i in range(len(li)-1):3 min_loc =i4 for j in range(i+1,len(li)):5 if li[j]

插入排序

列表被分为有序区和无序区两个部分。最初有序区只有一个元素。

每次从无序区选择一个元素,插入到有序区的位置,直到无序区变空。

需要记住两个概念,摸到的牌,手里的牌。

时间复杂度:O(n²)

1 definsert_sort(li):2 for i in range(1,len(li)):3 tmp =li[i]4 j = i - 1

5 while j>=0 and li[j] >tmp:6 li[j+1] =li[j]7 j = j - 1

8 li[j+1] = tmp

快速排序:快

写好的排序算法里最快的

快的排序算法里最好写的

时间复杂度:O(nlogn)

需要记住两个概念,整理,递归。

快排的思路:

1.取一个元素p(第一个元素),使元素p归位;

2.列表被p分成两个部分,左边都比p小,右边都比p大;

3.递归完成排序。

1 defpartition(data,left,right):2 tmp =data[left]3 while left < right and left <4 while data>=tmp:5 right = right - 14>

6 data[left] =data[right]7 while left < right and data[left] <=tmp:8 left = left +1

9 data[right] =data[left]10 data[left]=tmp11 returnleft12

13 defquick_sort(data,left,right ):14 if left <15 mid="partition(data,left,right)16" quick_sort>

堆排序--树与二叉树简介

树是一种数据结构    比如:目录结构

树是一种可以递归定义的数据结构

树是由n个节点组成的集合:

如果n=0,那这是一颗空树;

如果n>0,那存在1个节点作为树的根节点,其他节点可以分为m个集合,每个集合本身又是一棵树。

一些概念

根节点、叶子节点

树的深度(高度)

树的度

孩子节点/父节点

子树

特殊且常用的树--二叉树

二叉树:度不超过2的树(节点最多有两个叉)

两种特殊二叉树

满二叉树

完全二叉树

二叉树的存储方式

链式存储方式

顺序存储方式(列表)

父节点和左孩子节点的编号下标有什么关系?

0-1  1-3  2-5     3-7      4-9       i - 2i+1

父节点和右孩子节点的编号下标有什么关系

0-2  1-4  2-6  3-8  4-10  i - 2i+2

堆:

大根堆:一颗完全二叉树,满足任一节点都比其孩子节点大

小根堆:一个完全二叉树,满足任一节点都比其孩子节点小

堆排序过程

1.建立堆

2.得到堆顶元素,为最大元素。

3.去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一次调整重新使堆有序。

4.堆顶元素为第二大元素。

5.重复步骤3,直到堆变空。

时间复杂度:O(nlogn)

1 def sift(data,low,high): #调整

2 i =low3 j = 2*i+1

4 tmp=data[i]5 while j<=high: #省长已经是村民了

6 if j+1 <=high and data[j]< data[j+1]:7 j+=1

8 if tmp

12 else: #省长能罩住下一级孩子

13 break

14 data[i] =tmp15

16 defheap_sort(data):17 n =len(data)18 for i in range(n//2-1,-1,-1): #建堆时low变high不变 i代表low

19 sift(data,i,n-1)20 #建堆完成

21 for j in range(n-1,-1,-1): #j代表high ,挨个出数时 high变low不变

22 data[0],data[j] =data[j],data[0]23 sift(data,0,j-1)

归并排序

假设现在的列表分成两段有序,如何将其合成为一个有序列表

两各列表都是有序列表,从第一个数据拿出来进行对比,如果小的数据就拿出来。

时间复杂度:O(nlogn)

这种操作我们叫做一次归并。

分解:将列表越分越小直至分成一个元素。

一个元素是有序的。

合并:将两个有序列表归并,列表越来越大。

1 defmerge(data,low,mid,high):2 i =low3 j = mid+1

4 ltmp =[]5 while i <=mid and j<=high:6 if data[i]<=data[j]:7 ltmp.append(data[i])8 i += 1

9 else:10 ltmp.append(data[j])11 j += 1

12 while i<=mid:13 ltmp.append(data[i])14 i += 1

15 while j <=high:16 ltmp.append(data[j])17 j += 1

18 data[low:high+1] =ltmp19 #j = 0

20 #for i in range(low,high+1):

21 #data[i]=ltmp[j]

22 #j+=1

23

24 defmerge_sort(data,low,high):25 if low <26 mid="(low+high)//2</p">

27 merge_sort(data,low,mid)28 merge_sort(data,mid+1,high)29 merge(data,low,mid,high)

希尔排序

希尔排序是一种分组插入排序算法。

首先取一个整数d1 = n/2,将元素分为d1个组,每组相邻量元素之间距离为d1,在各组内进行直接插入排序;

取第二个整数d2 = d1/2,重复上述分组排序过程,直到di=1,既所有元素在同一组内进行直接插入排序。

希尔排序每趟并不适这些元素有序,而是使整体数据越来越接近有序;最后一趟排序使得所有数据有序。

排序-小结

快速排序、堆排序、并归排序 三种排序算法的时间复杂度都是O(nlogn)

一般情况下,就运行时间而言:

快速排序

三种排序算法的缺点:

快速排序:计算情况下排序效率低;不稳定

并归排序:需要额外的内存开销

堆排序:在快的排序算法中相对较慢;不稳定

排序方法

最坏情况

平均情况

最好情况

稳定性

代码复杂度

冒泡排序

O(n²)

O(n²)

O(n²)

稳定

简单

直接选择排序

O(n²)

O(n²)

O(n²)

不稳定

简单

直接插入排序

O(n²)

O(n²)

O(n²)

稳定

简单

快速排序

O(n²)

O(nlogn)

O(nlogn)

不稳定

较复杂

堆排序

O(nlogn)

O(nlogn)

O(nlogn)

不稳定

复杂

归并排序

O(nlogn)

O(nlogn)

O(nlogn)

稳定

较复杂

希尔排序

O(1.3n)

不稳定

较复杂

ps:python 内置函数有堆的使用   可以百度自己查询使用方法  heapq模块

26>15>27>21>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值