这个主题真的是我觉得所有算法主题里面最喜欢的主题之一。
从一个初始开始,不断调用自己,然后终于在一个终结条件上,那回了最终的答案,然后一直回溯,交给上一个自己。就像一个磅礴的大气的史诗神话。就像是宇宙从一个节点开始,不断的变大,增熵的过程,然后终于在最后的条件上,打碎了所有的循环,重新回到了bigbang的最初原点,拿回了那个真理。如果空间不足,就会stackoverflow,要么破灭,要么圆满。太中二,太美好了,完全就是宇宙的缩影。
代码简介而优雅,只要你懂得了这个宇宙的因果链就能一下子理解。
当我们说 “递归算法” 时,通常指的是一个函数在解决问题的过程中调用自身的一种技巧。递归算法涉及到将一个大问题拆分为更小的相似子问题,通过解决这些子问题最终得到整个问题的解。解决的是子问题也就是更小的问题这件事,比较重要,也就是每次都要更靠近base case一些,不然如果整个过程不断增大,是永远不可能得到最终结果的。
递归函数通常有两部分:
一个是基本情况(Base Case): 在递归算法中,必须有一个或多个基本情况,它们是递归终止的条件。在阶乘的例子中,基本情况是当 n 等于 0 或 1 时,阶乘的值是 1。另一个是递归调用: 在函数内部,通过调用自身解决规模更小的子问题。在阶乘的例子中,递归调用是计算 (n-1)!。
在树结构的遍历,分治问题中都有广泛应用。
提到递归,不可避免的会和迭代进行比较。为了避免堆栈溢出问题,迭代使用更新变量的方式,重复执行代码。
# Recursive implementation of n! (n-factorial) calculation
def factorial(n):
# Base case: n = 0 or 1
if n <= 1:
return 1
# Recursive case: n! = n * (n - 1)!
return n * factorial(n - 1)
不使用递归的方法:
def factorial(n):
result = 1
if n >= 1:
for i in range(1, n + 1):
result *= i
return result
# Recursive implementation to calculate the n-th Fibonacci number
def fibonacci(n):
# Base case: n = 0 or 1
if n <= 1:
return n
# Recursive case: fib(n) = fib(n - 1) + fib(n - 2)
return fibonacci(n - 1) + fibonacci(n - 2)
一样可以将大问题分为小问题。
基本情况是如果只有一个字母或者没有字母,为真。如果收尾不相等,为假。然后不断剥离首尾,判断子字符是否是回文即可。经典!
def isPalindrome(str):
# base case #1
if len(str) == 0 or len(str) == 1:
return True
# base case #2
if str[0] != str[len(str) - 1]:
return False
# recursive case
return isPalindrome(str[1: len(str) - 1])
四个情况的解释:很棒
def power(x, n):
# base case
if n == 0:
return 1
# recursive case: n is negative
if n < 0:
return 1 / power(x, -1 * n)
# recursive case: n is odd
if n % 2 == 0:
return power(x, n / 2) * power(x, n / 2)
# recursive case: n is even
if n % 2 != 0 :
return power(x, n - 1) * x