Python数据结构与算法:一文带你跨过“递归”门槛

注:今天博主开始更新数据结构与算法中的排序算法系列,使用Python语言实现,涉及基本数据结构、十大排序算法、递归分治、贪心动归等,意在帮大家更加容易的学习数据结构与算法以及进一步梳理这些知识点。

目录

递归的组成结构

如何凑集一笔巨款用于公益事业?

算法代码

总结

递归算法的执行

斐波那契序列

​算法代码

跟踪递归函数的执行过程

求斐波那契序列算法的时间复杂度

利用递归算法求解问题-判断回文

简单实现:时间复杂度为O(n)

递归实现

利用递归算法求解问题-全排列

利用递归算法求解问题-汉诺塔问题

利用递归算法求解问题-雪花曲线


递归的组成结构

首先来了解一下冰桶游戏:参与者在网 络上发布自己被冰水浇遍全身的视频内容,然后邀请3位朋友参加该活动

朋友要么24小时内接受挑战,要么选择向对抗“渐冻症”组织捐款100美元,仅在美国就有170 万参与挑战,250 万捐款,总额达1.15 亿美元

如何凑集一笔巨款用于公益事业?

  • 找朋友(众人拾材火焰高)
  • 确定策略(朋友愿意帮你)
  • 如何说服朋友愿意帮你
  • 募捐到你额度的分之

如果你需要募集100 万,那么他们各⾃需要募集10 万,他们不需要真的捐钱,而是按照你给的策略去募集10万,把你的方法传递下去。筹款的算法如下:

算法代码

def collect_contributions(n):
#n为需要筹集的款数
   if (n<=100):
      return 100 #需要此人捐出100元
   else:
      #寻找10个朋友
      friends= find_friend()
      sum = 0
      for i in range(len(friends)):
         # 从这10个朋友中分别募集n/10元
         sum += collect_contributions(n/10)
      return sum

总结

  • 分解问题(找朋友)
  • 递归求解(相同的策略)
  • 边界条件(求解/计算)

递归算法的两个要素:

  • 必须有最终停发展下线的边界条件,否则无穷循环
  • 必须有与原始问题结构致,但输规模于原始问题规模的递归结构

递归算法的执行

斐波那契算盘书》:⼀对兔⼦饲养在围墙中,如果它们每个⽉⽣⼀对兔⼦,且新⽣的兔⼦在第⼆个⽉后也是每个⽉⽣⼀对兔⼦,问⼀年后围墙中共有多少对兔⼦。斐波那契的分析如下:第⼀个⽉是最初的⼀对兔⼦⽣下⼀对兔⼦,围墙内共有两对兔⼦;第⼆个⽉仍是最初的⼀对兔⼦⽣下⼀对兔⼦,共有3对兔⼦;到第三个⽉除最初的兔⼦新⽣⼀对兔⼦外,第⼀个⽉⽣的兔⼦也开始⽣兔⼦,因此共有5 对兔⼦。24 个⽉共有⼏对兔⼦?

斐波那契序列


算法代码

def fib_rec(n):
   if n <= 1:
      f = n
   else:
      f = fib_rec(n-1) + fib_rec(n-2)
   return f
if __name__ == '__main__':
   num = 24
   print('fib({0})==>{1}'.format(num,fib_rec(num)))

跟踪递归函数的执行过程

求斐波那契序列算法的时间复杂度

利用递归算法求解问题-判断回文

回文定义: ⼀个正向和反向读是相同的字符串

  • level,noon
  • 蜜蜂酿蜂蜜,静泉泉静,上海海上

当给定个字符串str,需要判断该字符串是否为回⽂<如果是回⽂返回True,否则返回False

简单实现:时间复杂度为O(n)

递归实现

不妨设已经有个函数 is_palindrome(s)可以来求解该问题,不妨设 s=’level’

def is_palindrome(s):
   if len(s) <= 1:
      return True
   else:
      return s[0] == s[-1] and is_palindrome(s[1:-1])

第2行边界条件,第5行递归。时间复杂度为o(n)。

利用递归算法求解问题-全排列

的字符s=“ABC”,由字符A,B 和C 组成的全排列为:[“ABC”, “ACB”, “BAC”, “BCA”, “CAB”, “CBA”]

不妨设求解原问题的函数为permutation(s),如何将问题进行分解形成子问题,从而可以寻求朋友的帮助?

def permutation(str):
   lenstr = len(str)
   if lenstr < 2:#边界条件
      return str
   else:
      result = []
      for i in range(lenstr):
         ch = str[i]   #取出str中每一个字符
         rest = str[0:i] + str[i+1:lenstr]
         for s in permutation(rest): #递归
            result.append(ch + s) #将ch与子问题的解依次组合
   return result

对于长度为n 的输⼊字符串,共有n! 个全排列,因此代码的时间复杂度为O(n!)

利用递归算法求解问题-汉诺塔问题

每次只能移动个盘⼦,移动过程中,的盘不能处于的盘

不妨设有函数hanoi( )可以求解该问题,函数参数如何设计?

函数hanoi(n, S=‘A’, T=‘B’,H=‘C’) 可以求解该问题,其中n 为盘数,A, B 和C 分别为三个柱,S 表出发的柱,T 为的柱,H 为过渡

def hanoi(n,source,target,helper):
   if n==1:                         # 边界条件
      moveSingleDesk(source,target)
   else:
      hanoi(n-1,source,helper,target) # 将n-1个盘从A移到C
      moveSingleDesk(source,target)  # 将A中最大的一个盘从A移到B
      hanoi(n-1,helper,target,source) # 将n-1个盘从C移到B
def moveSingleDesk(source,target):
   disk = source[0].pop()
   print("moving " + str(disk) + " from " + source[1] + " to " + target[1])
   target[0].append(disk)

利用递归算法求解问题-雪花曲线

瑞典科赫于1904年提出了著名的“雪花”曲线

  • 如果n=0,直接画出L 长的直线即可。如果n=1(第次迭代),画出长度为L/3 的线段;画笔向左转60 度再画长度为L/3 长的线段;画笔向右转120 度画长度为L/3 长的线段;画笔再向左转60 度画出长度为L/3 的线段。
  • 如果n>1,第n 次迭代相当于:第n-1 次迭代;画笔左转60 度;n-1 次迭代;画笔右转120 度;第n-1 次迭代;画笔左转60 度;第n-1 次迭代。
  • 其中,第n >1 次迭代线段长度为L,第n 次迭代时线段长度则为L/3

import turtle
def koch(t,order,size):
   if order ==0:               # 边界条件
      t.forward(size)
   else:
      koch(t,order-1,size/3) # 递归调用
      t.left(60)          # 笔转60度
      koch(t,order-1,size/3) # 递归调用
      t.right(120)         # 笔转120度
      koch(t,order-1,size/3) # 递归调用
      t.left(60)          # 笔转60度
      koch(t,order-1,size/3) # 递归调用

 

相应面试题可参考如下内容或者前往公众号查看更多内容:

BAT大厂数据分析面试经验:“高频面经”之数据分析篇

BAT大厂数据挖掘面试经验:“高频面经”之数据结构与算法篇

BAT大厂数据开发面试经验:“高频面经”之大数据研发篇

BAT大厂机器学习算法面试经验:“高频面经”之机器学习篇

BAT大厂深度学习算法面试经验:“高频面经”之深度学习篇

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值