Discussion 5: Tree Recursion🖨️

IMPORTANT! Add your email address and then press "Join Group" above!

Getting Started

Say your name and your favorite tree (a particular tree or a kind of tree) in honor of today's topic: tree recursion.

Definition: Tree recursive functions are functions that call themselves more than once.

Recursion takes practice. Please don't get discouraged if you're struggling to write recursive functions. Instead, every time you do solve one (even with help or in a group), make note of what you had to realize to make progress. Students improve through practice and reflection.

VERY IMPORTANT: In this discussion, don't check your answers until your whole group is sure that the answer is right. Figure things out and check your work by thinking about what your code will do. Your goal should be to have all answers right the first time! If you need help, ask.

Tree Recursion

For the following questions, don't start trying to write code right away. Instead, start by describing the recursive case in words. Some examples:

  • In fib from Section 1.7 of the textbook, the recursive case is to add together the previous two Fibonacci numbers.
  • In skip_factorial from Lab 4 (Q2), the recursive case is to multiply n by the skip factorial of n - 2.
  • In count_partitions from Section 1.7 of the textbook, the recursive case is to partition n-m using parts up to size m and to partition n using parts up to size m-1.

Q1: Insect Combinatorics

An insect is inside an m by n grid. The insect starts at the bottom-left corner (1, 1) and wants to end up at the top-right corner (m, n). The insect can only move up or to the right. Write a function paths that takes the height and width of a grid and returns the number of paths the insect can take from the start to the end. (There is a closed-form solution to this problem, but try to answer it with recursion.)

Insect grids.

In the 2 by 2 grid, the insect has two paths from the start to the end. In the 3 by 3 grid, the insect has six paths (only three are shown above).

Hint: What happens if the insect hits the upper or rightmost edge of the grid?

def paths(m: int, n: int) -> int:
    """Return the number of paths from one corner of an
    m by n grid to the opposite corner.

    >>> paths(2, 2)
    2
    >>> paths(5, 7)
    210
    >>> paths(117, 1)
    1
    >>> paths(1, 157)
    1
    """
    "*** YOUR CODE HERE ***"
Recursive Case

From any square, what are the insect's only two possible next moves? After either one, it is in a smaller grid with the same goal corner. If you knew the number of paths from each of those two squares, how would you get the number of paths from the current square?

Presentation Time: Once your group has converged on a solution, it's time to practice your ability to describe why your recursive case is correct. Nominate someone and have them present to the group for practice. If you want feedback, ask.

Q2: A Perfect Question

This question was Fall 2023 Midterm 2 Question 4(a) (find it with the other past exams). The original exam version had an extra blank (where total < k * k appears below), but also included some guidance via multiple choice options and hints.

Definition. A perfect square is k*k for some integer k.

Implement fit, which takes positive integers total and n. It returns True or False indicating whether there are n positive perfect squares that sum to total. The perfect squares need not be unique.

def fit(total: int, n: int) -> bool:
    """Return whether there are n positive perfect squares that sums to total.

    >>> [fit(4, 1), fit(4, 2), fit(4, 3), fit(4, 4)]  # 1*(2*2) for n=1; 4*(1*1) for n=4
    [True, False, False, True]
    >>> [fit(12, n) for n in range(3, 8)]  # 3*(2*2), 3*(1*1)+3*3, 4*(1*1)+2*(2*2)
    [True, True, False, True, False]
    >>> [fit(32, 2), fit(32, 3), fit(32, 4), fit(32, 5)] # 2*(4*4), 3*(1*1)+2*2+5*5
    [True, False, False, True]
    """
    def f(total, n, k):
        if ____:
            return True
        elif total < k * k:
            return False
        else:
            return ____
    return f(total, n, 1)
Why the False cases are False
  • fit(4, 2) and fit(4, 3): the only positive squares up to 4 are 1 and 4, and no two or three of them sum to 4 (1 + 1, 1 + 4, 4 + 4, 1 + 1 + 1, ... none equal 4).
  • fit(12, 5) and fit(12, 7): every square up to 12 is 1, 4, or 9. Five squares sum to 5 plus some 3s (a 4 is 1 + 3) and 8s (a 9 is 1 + 8), and 12 - 5 = 7 can't be made from 3s and 8s. Likewise 12 - 7 = 5 for seven.
  • fit(32, 3) and fit(32, 4): 16 + 16 reaches 32 with only two squares, and no three or four squares from 1, 4, 9, 16, 25 sum to 32.

Tree Recursion with Lists

Some of you already know list operations that we haven't covered yet, such as append. Don't use those today. All you need are list literals (e.g., [1, 2, 3]), item selection (e.g., s[0]), list addition (e.g., [1] + [2, 3]), len (e.g., len(s)), slicing (e.g., s[1:]), for statements, range, and list comprehensions. Use those!

Important: The most important thing to remember about lists is that a non-empty list s can be split into its first element s[0] and the rest of the list s[1:]. Slicing works from other positions too: s[2:] is everything after the first two elements. Slicing past the end of a list never errors; it just gives [] (see the List Slicing review in Lab 5).

>>> s = [2, 3, 6, 4]
>>> s[0]
2
>>> s[1:]
[3, 6, 4]
>>> s[2:]
[6, 4]
>>> len(s)
4
>>> s[4:]
[]
>>> [][1:]
[]

Q3: Max Product

Implement max_product, which takes a list of integers and returns the maximum product that can be formed by multiplying together non-consecutive elements of the list. Assume that all numbers in the input list are greater than or equal to 1.

def max_product(s: list[int]) -> int:
    """Return the maximum product of non-consecutive elements of s.

    >>> max_product([10, 3, 1, 9, 2])   # 10 * 9
    90
    >>> max_product([5, 10, 5, 10, 5])  # 5 * 5 * 5
    125
    >>> max_product([5, 10, 5, 10, 5, 10]) # 10 * 10 * 10
    1000
    >>> max_product([])                 # The product of no numbers is 1
    1
    """
    "*** YOUR CODE HERE ***"
Hint

First try multiplying the first element by the max_product of everything after the first two elements (skipping the second element because it is consecutive with the first), then try skipping the first element and finding the max_product of the rest. To find which of these options is better, use max.

More Help

A great way to get help is to talk to the course staff!

Description Time: Now try to complete this sentence together: "The recursive case is to choose the larger of ___ and ___." When you're done, see how your answer compares to ours.


Back to Top

Accessibility Nondiscrimination

Copyright ©2026, Regents of the University of California and respective authors.

This site is built following the Berkeley Class Site template, which is generously based on the Just the Class, and Just the Docs templates.

View all course offerings