再谈递归

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:

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)


全部评论

相关推荐

黑皮白袜臭脚体育生:简历统一按使用了什么技术实现了什么功能解决了什么问题或提升了什么性能指标来写会更好另外宣传下自己的开源仿b站微服务项目,GitHub已经410star,牛客上有完整文档教程,如果觉得有帮助的话可以点个小星星,蟹蟹
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务