1、算法

  1. 英文名:algorithm,就是计算的方法。
    # 是截止到目前,人类发现的针对特定场景的,最优的计算方法。是人类智慧的结晶。
    # 人脑是复杂的,电脑其实很简单。比如:
  2.  
  3. 999 * 123 人类会将其变为: 1000 * 123 - 123 这样就好算多了,可是电脑不会如此,只会硬算!
  1. 学习算法的目的
    # 我们学习的算法 都是过去时
    # 了解基础的算法 才能创造出更好的算法
    # 不是所有的事情都能套用现成的方法解决的
    # 有些时候会用到学过的算法知识来解决新的问题

2、递归

1)、楔子

  1. 有如下例子:
    从前有座山,山上有个庙;庙里有两个和尚,一个老和尚跟一个小和尚。一天,老和尚跟小和尚讲故事:
    "从前有座山,山上有个庙;庙里有两个和尚,一个老和尚跟一个小和尚。一天,老和尚跟小和尚讲故事:
    '从前有座山,山上有个庙;庙里有两个和尚,一个老和尚跟一个小和尚。一天,老和尚跟小和尚讲故事:
    .............................
  1. # 看到这个例子,有何感想?这不是车轱辘话码,自己说自己!
    # 这就对了,我们就正式引入递归!
  1. 2)、递归函数的定义
  1. 在函数中,自己调用自己的函数,叫递归函数。
  1. depth = 0
  2. def temple_story():
  3. global depth
  4. print('从前有座山,山上有个庙;庙里有两个和尚,一个老和尚跟一个小和尚。一天,老和尚跟小和尚讲故事:')
  5. depth += 1
  6. print(depth)
  7. temple_story()
  8.  
  9. #temple_story() #会报告超过最大递归深度的错误!
  10. # 报错:RecursionError: maximum recursion depth exceeded while calling a Python object
  11.  
  12. # 我们来看看这个深度是多少?添加计数,发现是997次!
  13. # 这个最大递归次数是python定义的,可以改,但建议如此做,因为递归如此多,还解决不了,就说明不适合用递归解决!
  14. import sys
  15. print("最大递归深度是:", sys.getrecursionlimit()) #
  16. sys.setrecursionlimit(50000)
  17.  
  18. #temple_story() # 没有报告错误!执行到3806次就没打印了(并且退出了函数),说明有东西限制了继续递归!
  1. 3)、递归的小结
  1. # 如果递归次数太多,就不适合使用递归来解决问题
    # 递归的缺点 : 占内存
    # 递归的优点: 会让代码变简单
  1. 4)、应用场景1:询问年龄
  1. '''
  2. # alex 多大 n = 1 age(1) = age(2)+2 = age(n+1) + 2
  3. # alex比egon大两岁
  4. # egon多大? n = 2 age(2) = age(3) + 2 = age(n+1) +2
  5. # egon比tom大两岁
  6. # tom多大 n = 3 age(3) = age(4) + 2 = age(n+1) +2
  7. # tom比king大两岁
  8. # king多大?
  9. # king40了 n = 4 age(4) = 40
  10. '''
  11. def ask_age(n):
  12. '''
  13. 问年龄,
  14. :param n:被询问的序号
  15. :return: age
  16. '''
  17. if n == 4:
  18. return 40
  19. elif 0 < n < 4:
  20. return ask_age(n + 1) + 2
  21. print('I am ', ask_age(3))
  22.  
  23. # # 教你看递归 递的是n,归的是return的值
  24. # def ask_age(1):
  25. # if 1 == 4:
  26. # return 40
  27. # elif 1 > 0 and 1 < 4:
  28. # return 46
  29. #
  30. # def ask_age(2):
  31. # if 2 == 4:
  32. # return 40
  33. # elif 2 >0 and 2 < 4:
  34. # age(3) + 2 None +2
  35. #
  36. # def ask_age(3):
  37. # if 3 == 4:
  38. # return 40
  39. # elif 3 >0 and 3 < 4:
  40. #
  41. #
  42. # def ask_age(4):
  43. # if 4 == 4:
  44. # return 40
  45. # elif n >0 and n < 4:
  46. # age(n+1) + 2

3、二分法 (dichotomy),必须处理有序的列表

  1. # 使用实例:使用二分法查找数列中有没有66,并返回其索引。
  2. num_li = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
  3.  
  4. # 没接触二分法之前,我们大概会用for循环遍历数列,判断其中元素是否是66,如果是返回其索引!
  5. # 但是,想一想,如果此数列有几百万个元素,这样遍历会很慢,如何查找最快?答案是:二分法
  6. # 第一次,找到数列最中间的元素,比较它和66的大小,如果大于66,就说明66在它前面,前面的数又组成一个数列num_li_new_1,
  7. # 如果它比66小,则说明66在它的后面,将其后面的数,组成一个新的数列:num_li_new_2
  8. # 第二次,在num_li_new_1或者num_li_new_2中,继续按照第一的方法寻找下去。。。。。。
  9. # 第n次,如果有该元素,一定会找到它,而且只有一个元素了!
  10.  
  11. #1)、第一次尝试用二分法
  12. def find_num(list, target):
  13. mid_index = len(list)//2
  14. if list[mid_index] == target:
  15. print('Congratunation! You get it!')
  16. return mid_index
  17. elif list[mid_index] > target:
  18. new_list = list[:mid_index]
  19. find_num(new_list, target)
  20. else:
  21. new_list = list[mid_index + 1:]
  22. find_num(new_list, target)
  23.  
  24. res = find_num(num_li, 67)
  25. print(res)
  26.  
  27. # 惊奇的发现,打印的结果是:None
  28. # 分析未得到预想结果的原因: todo:没有接收返回值,也没有返回任何值! 所以为None
  29. def find_num(list, target): # 第一步:list=num_li target = 67
  30. mid_index = len(list) // 2 # 第二步:mid_index = 24//2 = 12
  31. if list[mid_index] == target: # list[mid_index] = list[12] = 41
  32. print('Congratunation! You get it!')
  33. return mid_index
  34. elif list[ mid_index ] > target:
  35. new_list = list[ :mid_index ]
  36. find_num(new_list, target)
  37. else: #第三步:41 < 67
  38. new_list = list[ mid_index + 1: ] # 第四步:new_list = list[13:] = [42,43,55,56,66,67,69,72,76,82,83,88]
  39. find_num(new_list, target) # 第五步:find_num(new_list, 67)todo:没有接收返回值,也没有返回任何值!
  40.  
  41. def find_num(list, target): # 第六步:list=new_list target = 67
  42. mid_index = len(list) // 2 # 第七步:mid_index = 12//2 = 6
  43. if list[mid_index] == target: # list[mid_index] = list[6] = 69
  44. print('Congratunation! You get it!')
  45. return mid_index
  46. elif list[ mid_index ] > target: # 第八步:69 > 67
  47. new_list = list[ :mid_index ] # 第九步:new_list = list[:6] = [42,43,55,56,66,67]
  48. find_num(new_list, target) # 第十步:find_num(new_list, 67) todo:没有接收返回值,也没有返回任何值!
  49. else:
  50. new_list = list[ mid_index + 1: ] #
  51. find_num(new_list, target) #
  52.  
  53. def find_num(list, target): # 第十一步:list=new_list target = 67
  54. mid_index = len(list) // 2 # 第十二步:mid_index = 6//2 = 3
  55. if list[mid_index] == target: # list[mid_index] = list[3] = 56
  56. print('Congratunation! You get it!')
  57. return mid_index
  58. elif list[ mid_index ] > target: #
  59. new_list = list[ :mid_index ]
  60. find_num(new_list, target) # 第十步:find_num(new_list, 67)
  61. else: # 第十三步:56 < 67
  62. new_list = list[mid_index + 1:] # 第十四步:new_list = list[4:] = [66,67]
  63. find_num(new_list, target) # 第十五步: find_num(new_list, 67) todo:没有接收返回值,也没有返回任何值!
  64.  
  65. def find_num(list, target): # 第十六步: list=new_list target = 67
  66. mid_index = len(list)//2 # 第十七步:mid_index = 2//2 = 1
  67. if list[mid_index] == target: # 第十八步:list[mid_index] = list[1] = 67 正好相等!
  68. print('Congratunation! You get it!') # 第十九步:输出Congratunation! You get it!
  69. return mid_index # 第二十步:将mid_index = 1 todo 返回给调用该函数的地方:即第十五步
  70. elif list[mid_index] > target:
  71. new_list = list[:mid_index]
  72. find_num(new_list, target)
  73. else:
  74. new_list = list[mid_index + 1:]
  75. find_num(new_list, target)
  76.  
  77. #2)、第二次尝试用二分法
  78.  
  79. def find_num(list, target):
  80. mid_index = len(list)//2
  81. if list[mid_index] == target:
  82. print('Congratunation! You get it!')
  83. return mid_index
  84. elif list[mid_index] > target:
  85. new_list = list[:mid_index]
  86. return find_num(new_list, target)
  87. else:
  88. new_list = list[mid_index + 1:]
  89. return find_num(new_list, target)
  90.  
  91. res = find_num(num_li, 67)
  92. print(res)
  93.  
  94. # 继续惊奇的发现,结果是:0,这并不是我们预想的结果!
  95. # 原因分析:索引乱了,我们切分数列后,用的是新的索引!
  96.  
  97. # 3)、第三次尝试用二分法
  98.  
  99. #def find_num(list, target, start = 0, end = len(list)): #TypeError: object of type 'type' has no len()
  100. def find_num(list, target, start = 0, end = None):
  101. end = len(list) if end is None else end
  102. # mid_index = len(list)//2 # 有时会报错:IndexError: list index out of range
  103. mid_index = (end - start)//2 + start #
  104. if list[mid_index] < target:
  105. #new_list = list[ mid_index + 1:end ] # 加start和end后,不用传了,否者列表会越界!
  106. return find_num(list, target, start=mid_index + 1, end=end)
  107. elif list[mid_index] > target:
  108. #new_list = list[start:mid_index]
  109. return find_num(list, target, start=start, end=mid_index)
  110. else:
  111. print('Congratunation! You get it!')
  112. return mid_index
  113.  
  114. res = find_num(num_li, 66)
  115. print(res)
  116.  
  117. # 结果是出现了,还发现一个问题,如果查找的数不在列表中,会报错:RecursionError: maximum recursion depth exceeded in comparison
  118.  
  119. # 4、第四次
  120. def find_num(list, target, start = 0, end = None):
  121. end = len(list) if end is None else end
  122. if end > start:
  123. mid_index = (end - start)//2 + start #
  124. if list[mid_index] < target:
  125. return find_num(list, target, start=mid_index + 1, end=end)
  126. elif list[mid_index] > target:
  127. return find_num(list, target, start=start, end=mid_index)
  128. else:
  129. print('Congratunation! You get it!')
  130. return mid_index
  131. else:
  132. return '该数列中没有你找的数!'
  133.  
  134. res = find_num(num_li, 44)
  135. print(res)

Python进阶-Ⅸ 递归 二分法的更多相关文章

  1. python --- 14 递归 二分法查找

    一.递归 1.函数自己调用自己 2.官方说明最大深度1000,但跑不到1000,要看解释器, 实测998 3.使⽤递归来遍历各种树形结构 二.    二分法查找 掐头结尾取中间 ,  必须是有序序列 ...

  2. 【学习笔记】--- 老男孩学Python,day15 python内置函数大全,递归,二分法

    1. lamda匿匿名函数2. sorted()3. filter()4. map()5. 递归函数 一. lamda 匿名函数 为了了解决一些简单的需求⽽设计的⼀句话函数 语法: 函数名 = lam ...

  3. python之内置函数(lambda,sorted,filter,map),递归,二分法

    一.lambda匿名函数 为了解决一些简单需求而设计的一句话函数,lambda表示的是匿名函数,不需要用def来声明,一句话就可以声明出一个函数. 语法: 函数名 = lambda 参数 : 返回值 ...

  4. Python匿名函数/排序函数/过滤函数/映射函数/递归/二分法

    一. lamda匿名函数 为了解决一些简单的需求而设计的一句话函数 # 计算n的n次方 def func(n): return n**n print(func(10)) f = lambda n: n ...

  5. Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量

    Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量 一丶线程的理论知识 什么是线程:    1.线程是一堆指令,是操作系统调度 ...

  6. Python进阶(七)----带参数的装饰器,多个装饰器修饰同一个函数和递归简单案例(斐波那契数列)

    Python进阶(七)----带参数的装饰器,多个装饰器修饰同一个函数和递归简单案例(斐波那契数列) 一丶带参数的装饰器 def wrapper_out(pt): def wrapper(func): ...

  7. Python进阶5---StringIO和BytesIO、路径操作、OS模块、shutil模块

    StringIO StringIO操作 BytesIO BytesIO操作 file-like对象 路径操作 路径操作模块 3.4版本之前:os.path模块 3.4版本开始 建议使用pathlib模 ...

  8. python进阶06 常用问题库(2)datetime模块 base64

    python进阶06 常用问题库(2)datetime模块 base64 一.datetime模块(时间) 1.datetime.time() t=datetime.time(20,43,30,1) ...

  9. python进阶强化学习

    最近学习了慕课的python进阶强化训练,将学习的内容记录到这里,同时也增加了很多相关知识. 主要分为以下九个模块: 基本使用 迭代器和生成器 字符串 文件IO操作 自定义类和类的继承 函数装饰器和类 ...

随机推荐

  1. Vue 使用lodash库减少watch对后台请求压力

    lodash需要新引入 我使用的是npm方式 使用lodash的_.debounce方法 具体代码: <!doctype html> <html lang="en" ...

  2. P3十进制转换为二进制

    #include<stdio.h>int main ()   {    int n;    scanf("%d",&n);    int a[8];    fo ...

  3. 造轮子ArrayList

    这篇博客实现一个简单的ArrayList集合.博客里的代码首先根据自己的想法实现,在走不动的情况下会去参考JDK源代码.所以阅读本文,不要抱着跟JDK源码对比的心态.于我个人而言,国庆期间,纯属娱乐. ...

  4. background-size:100% 100% 和 background-size:cover的区别简述

    下面我通过给下图背景图添加background-size属性的不同属性值,更直观的显示出100%和cover的区别   下图是添加background-size:100% 100% 后的背景图效果,背 ...

  5. C#中文转换为拼音NPinyin代码【转】

    项目地址:https://code.google.com/p/npinyin/ 在一个采集的程序中,为了给每个文章起一个别名,据说有很好的别名的话,对于百度.google的收录 是很有好处的.按照Se ...

  6. Redis 主从同步+哨兵

    简介 通过使用 Redis 自带“主从同步+哨兵守护”功能提高Redis稳定性. 主从同步:保障数据主从数据实时同步. 哨兵:实时监控主redis如果故障,将从redis作为主使用. 环境: 系统:C ...

  7. 【题解】Informacije [COCI2012]

    [题解]Informacije [COCI2012] 传送门:官方题面 [题目描述] 有一个长度为 \(n\) 的 序列 \(a\)(由 \([1,n]\) 中的数组成,且每个数只会出现一次),现给出 ...

  8. WPF,ComboBox,取汉字首字母,extBoxBase.TextChanged

    1取汉字汉语拼音首字母: private static string GetFirstLetterOfChineseString(string CnChar) { long iCnChar; byte ...

  9. NET 判断是否为回文

    比如: 12321,第一位等于第五位,第二位等于第四位 /// <summary> /// 判断是否为回文 /// 比如:12321,第一位等于第五位,第二位等于第四位 /// </ ...

  10. 1. mvc 树形控件tree + 表格jqgrid 显示界面

    1.界面显示效果 2.资源下载 地址 1. jstree  https://www.jstree.com/   2.表格jqgrid  https://blog.mn886.net/jqGrid/  ...