再谈递归

1 Recursion

A recursive function is a function that calls itself, either directly or indirectly.

Here’s a recursive function:

def factorial(n):
    """ Returns the result of n!

    >>> factorial(0)
    1
    >>> factorial(1)
    1
    >>> factorial(4)
    24
    """
    if n == 0 or n == 1:
        return 1
    else:
        return n * factorial(n-1)

Although we haven’t finished defining factorial, we are still able to call it since the function body is not evaluated until the function is called. We do have one base case : when n is 0 or 1. Now we can compute factorial (2) in terms of factorial(1), and factorial(3) in terms of factorial(2),…

There are three common steps in a recursive definition:

  1. Figure out your base case(s) : What is the simplest argument we could possiblely get ? For example, factorial(0) is 1 by definition.

  2. Make a recursive call with a simpler argument : Simplify your problem, and assume that a recursive call for this new problem will simply work. This is called the “leap of faith”. For factorial, we reduce the problem by calling factorial(n-1).

  3. Use your recursive call to solve the full problem : Remember that we are assuming the recursive call works. With the result of the recursive call, how can you solve the original problem you were asked? For factorial, we just multiply (n-1)! by n.

Questions

Create a recursive countdown function that takes in an integer n and prints out a
countdown from n to 1.

  • 1.1 First, think about a base case for the countdown function. What is the simplest input the problem could be given?

    when n equals 0

  • 1.2 After you’ve thought of a base case, think about a recursive call with a smaller argument that approaches the base case. What happens if you call countdown(n -
    1)?

    A countdown starting from n-1 is printed.

  • 1.3 Then, put the base case and the recursive call together, and think about where a
    print statement would be needed.

def countdown(n):
    """
    >>> countdown(3)
    3
    2
    1
    """
    if n <= 0:           #base case
        return
    print(n)
    countdown(n-1)       #recursive call
  • 1.4 Is there an easy way to change countdown to count up instead?
def countup(n):
    """
    >>> countup(3)
    1
    2
    3
    """
    if n <= 0:
        return
    countup(n-1)
    print(n)
  • Explaining: Solving countup

    • Leap of Faith

      1. Base case

        • Smallest possible input.
        • if n == 1 or maybe n < 1
      2. Reduce the problem

        • To print the number before us, try n - 1
      3. Solve the larger problem

        • Need to print our own number as well
        • print(n)
    • Enumeration

      1. List the cases

        • if n == 1:
          print(1)
        • if n == 2:
          print(1)
          print(2)
      2. Identify the pattern

        • n == 2 helps n == 3
      3. Simplify with recursion

        • if n == 3:
          countup(2)
          print(3)

2 Iteration vs. Recursion

  • Example 1: factorial
#recursive way
def recursive_fact(n):
    if n == 0 or n == 1:
        return 1
    else:
        return n * recursive_fact(n-1)

#iterative way
def iterative_fact(n):
    total = 1
    while n > 1:
        total, n = total * n, n - 1
    return total
  • Example 2: fibonacci
#recursive way
def recursive_fib(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return recursive_fib(n-2) + recursive_fib(n-1)

#iterative way
def iterative_fib(n):
    prev, curr = 0, 1
    while n > 0:
        prev, curr = curr, prev + curr
        n = n -1
    return prev
  • Iteration is a special case of recursion
  • For the recursive version, we copied the definition of the Fibonacci sequence straight into code! The nth Fibonacci number is simply the sum of the two before it. In iteration, you need to keep track of more numbers and have a better understanding of the code.

3 Tree Recursion

Consider a function that requires more than one recursive call. Such as fibonacci function.

#The fibonacci sequence
n:      0, 1, 2, 3, 4, 5, 6,  7,  8, ... ,    35 
fib(n): 1, 1, 2, 3, 5, 8, 13, 21, ... , 9,227,465    
def fib(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fib(n-2) + fib(n-1)

This type of recursion is called tree recursion, because it makes more than one recursive call in its recursive case. If we draw out the recursive calls, we see the recursive callse in the shape of an upside-down tree:
fibonacci

We could, in theory, use loops to write the same procedure. However, problems that are naturally solved using tree recursive procedures are generally difficult to write iteratively. As a general rule of thumb, whenever you need to try multiple possibilities at the same time, you should consider using tree recursion.

Questions

I want to go up a flight of stairs that has n steps. I can either take 1 or 2 steps each time. How many different ways can I go up this flight of stairs? Write a function count stair ways that solves this problem for me. Assume n is positive.

  • 3.1 Before we start, what’s the base case for this question? What is the simplest input?

    (1) When there is only 1 step, there is only one way to go up the stairs.
    (2)When there are 2 steps, there are two ways: take a two-step, or take 2 one-steps

  • 3.2 What do count stair ways(n - 1) and count stair ways(n - 2) represent?

    (1)count stair ways(n - 1) represents the number of different ways to go up the last n − 1 stairs.
    (2)count stair ways(n - 2) represents the number of different ways to go up the last n − 2 stairs.
    Our base cases will take care of the remaining 1 or 2 steps.

  • 3.3 Use those two recursive calls to write the recursive case:

def count_stair_ways(n):
    if n == 1:
        return 1
    elif n == 2:
        return 2
    else:
        return count_stair_ways(n-1) + count_stair_ways(n-2)

Summary

  • Recursive functions call themselves , either directly or indirectly, in the function body.
    • The motivation for this is to break down the problem into smaller, easier to solve problems
    • In environment diagrams, each call creates its own frames and keep track of its own argument values
  • Recursive functions have base case(s) , which evaluate without relying on calls to itself, and recursive case(s)
    • When writing recursive calls, remember the three common steps
    • And use both the leap of faith and enumeration(Example: such as Question 1.4)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值