0Pricing
Coding Interview Prep · Aula

Estrutura da Recursão: Caso Base, Confiança, Construção

Aplique o método de três etapas para escrever soluções recursivas corretas para fatorial, potência e soma de dígitos sem rastrear cada chamada.

Estrutura da Recursão: Caso Base, Confiança, Construção é uma aula grátis de Coding Interview Prep no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Coding Interview Prep, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Coding Interview Prep inclui 4 aulas no total.

Por que a recursão parece difícil

A maioria dos iniciantes tenta acompanhar mentalmente cada chamada recursiva, o que rapidamente se torna confuso até mesmo em uma recursão com cinco níveis de profundidade. A abordagem profissional usa uma estrutura de três etapas — Caso-base, Confiança e Construção — que permite escrever funções recursivas corretas sem simular mentalmente toda a árvore de chamadas.

Às vezes, essa estrutura é chamada de ato de fé: você confia que sua função funciona para entradas menores e usa essa suposição para construir a solução para entradas maiores.

Etapa 1: Defina o caso-base

O caso-base é a entrada mais simples para a qual a resposta é conhecida sem mais recursão. Toda função recursiva deve ter pelo menos um caso-base; sem ele, a função recursa indefinidamente (estouro da pilha). Bons casos-base são: lista vazia, elemento único, n == 0, n == 1 ou quando o problema se reduz a uma identidade trivial.

Escreva primeiro o caso-base, antes de qualquer lógica recursiva. Identifique-o perguntando: 'Qual é a menor versão deste problema que posso responder imediatamente?'

# Base cases for common problems
def factorial(n):
    if n == 0:          # base case: 0! = 1
        return 1
    # ... recursive step below

def sum_list(lst):
    if not lst:         # base case: sum of empty list is 0
        return 0
    # ...

def height(node):
    if node is None:    # base case: height of null node is 0
        return 0
    # ...

print('Base cases identified')

Etapa 2: Confie na chamada recursiva

A etapa de confiança é um salto de fé: suponha que sua função já funcione corretamente para qualquer entrada estritamente menor que a atual. Você não precisa provar isso agora para cada entrada menor — a prova por indução garante essa conclusão. Simplesmente chame sua função no subproblema menor e confie que ela retornará o resultado correto.

Esta é a etapa que os iniciantes costumam ignorar, tentando simular tudo mentalmente. Resista a esse impulso; a abordagem funciona até para recursões arbitrariamente profundas depois que você internaliza a estrutura.

# Trust example: sum_list([3, 1, 4, 1, 5])
# Trust: sum_list([1, 4, 1, 5]) = 11  (we TRUST this, don't trace it)
# Build: 3 + 11 = 14

# So:
def sum_list(lst):
    if not lst:
        return 0
    # Trust that sum_list(lst[1:]) returns sum of the rest
    return lst[0] + sum_list(lst[1:])

print(sum_list([3, 1, 4, 1, 5]))  # 14

Etapa 3: Construa a solução

A etapa de construção combina o resultado confiável do subproblema com a contribuição do elemento atual para produzir a resposta para a entrada completa. Normalmente, isso ocupa uma única linha: aplique uma operação ao elemento atual e ao resultado da chamada recursiva. Construções comuns: adicionar à soma, inserir no início da lista, incrementar a contagem, combinar dois resultados de subproblemas.

def factorial(n):
    if n == 0:
        return 1
    # Trust: factorial(n-1) gives (n-1)!
    # Build: n * (n-1)! = n!
    return n * factorial(n - 1)

def power(base, exp):
    if exp == 0:
        return 1
    # Trust: power(base, exp-1) gives base^(exp-1)
    # Build: base * base^(exp-1) = base^exp
    return base * power(base, exp - 1)

print(factorial(6))    # 720
print(power(2, 10))    # 1024

Aplicando a estrutura à soma dos dígitos

Problema: calcular a soma dos dígitos de um inteiro não negativo. Caso-base: n == 0 → a soma é 0 (ou n < 10 → o próprio n). Confiança: sumDigits(n // 10) retorna a soma de todos os dígitos, exceto o último. Construção: adicionar o último dígito n % 10 ao resultado confiável. A estrutura produz a solução em três etapas declarativas.

def sumDigits(n):
    if n < 10:
        return n            # base case: single digit
    # Trust: sumDigits(n // 10) gives sum of all digits except last
    # Build: add the last digit
    return n % 10 + sumDigits(n // 10)

print(sumDigits(0))      # 0
print(sumDigits(7))      # 7
print(sumDigits(123))    # 6
print(sumDigits(9999))   # 36

Fibonacci: dois subproblemas

Fibonacci exige duas chamadas recursivas: fib(n-1) e fib(n-2). Aplique a estrutura: os casos-base são fib(0) = 0 e fib(1) = 1. Confiança: ambas as chamadas menores retornam os valores corretos de Fibonacci. Construção: retorne a soma delas. Esta implementação ingênua tem complexidade O(2^n) — vamos corrigir isso na lição sobre memoização.

def fib(n):
    if n <= 1:
        return n      # base cases: fib(0)=0, fib(1)=1
    # Trust both smaller sub-problems
    return fib(n - 1) + fib(n - 2)

for i in range(8):
    print(f'fib({i}) = {fib(i)}')  # 0,1,1,2,3,5,8,13

Inverta uma cadeia de caracteres recursivamente

Problema: inverter uma cadeia de caracteres recursivamente. Caso-base: cadeia vazia ou caractere único — já está invertida. Confiança: reverse(s[1:]) retorna a inversão de tudo depois do primeiro caractere. Construção: adicionar o primeiro caractere ao final do sufixo invertido. A estrutura produz uma solução de três linhas.

def reverse_str(s):
    if len(s) <= 1:
        return s            # base case
    # Trust: reverse_str(s[1:]) = reverse of 'ello' for 'hello'
    # Build: append first character at end
    return reverse_str(s[1:]) + s[0]

print(reverse_str(''))        # ''
print(reverse_str('a'))       # 'a'
print(reverse_str('hello'))   # 'olleh'
print(reverse_str('racecar')) # 'racecar'

Conte ocorrências recursivamente

Problema: contar recursivamente as ocorrências de um valor-alvo em uma lista. Caso-base: lista vazia — a contagem é 0. Confiança: count(lst[1:], target) retorna a contagem na cauda. Construção: adicionar 1 se o primeiro elemento coincidir com o alvo; caso contrário, adicionar 0. Cada etapa recursiva avança em direção ao caso-base ao reduzir o tamanho da lista em 1.

def count_occurrences(lst, target):
    if not lst:
        return 0
    # Trust: count in rest of list is handled recursively
    # Build: add 1 if first element matches, else 0
    return (1 if lst[0] == target else 0) + count_occurrences(lst[1:], target)

print(count_occurrences([1, 2, 3, 2, 4, 2], 2))  # 3
print(count_occurrences([], 5))                    # 0
print(count_occurrences([7, 7, 7], 7))             # 3

Verifique se uma lista está ordenada

Problema: verificar recursivamente se uma lista está ordenada em ordem crescente. Caso-base: uma lista com 0 ou 1 elemento está sempre ordenada. Confiança: is_sorted(lst[1:]) informa se a cauda está ordenada. Construção: a lista está ordenada se o primeiro elemento for <= o segundo AND a cauda estiver ordenada. Este é um exemplo claro em que a etapa de construção usa um AND lógico de duas condições.

def is_sorted(lst):
    if len(lst) <= 1:
        return True
    # Trust: is_sorted(lst[1:]) tells us if tail is sorted
    # Build: head <= second element AND tail is sorted
    return lst[0] <= lst[1] and is_sorted(lst[1:])

print(is_sorted([]))           # True
print(is_sorted([1]))          # True
print(is_sorted([1, 2, 3, 4])) # True
print(is_sorted([1, 3, 2, 4])) # False

Busca binária recursiva (revisão)

Busca binária expressa recursivamente por meio da estrutura: caso-base: lo > hi → não encontrado (retorne -1). Confiança: a chamada recursiva na metade correta encontra o alvo ou retorna -1. Construção: calcular mid, comparar e chamar a metade apropriada. A forma recursiva mostra claramente a estrutura de divisão e conquista, embora a forma iterativa seja preferida em produção por usar espaço O(1).

def binary_search(arr, target, lo, hi):
    if lo > hi:          # base case: search space exhausted
        return -1
    mid = lo + (hi - lo) // 2
    if arr[mid] == target:
        return mid
    # Trust both halves return correct results
    if arr[mid] < target:
        return binary_search(arr, target, mid + 1, hi)
    else:
        return binary_search(arr, target, lo, mid - 1)

arr = [1, 3, 5, 7, 9, 11]
print(binary_search(arr, 7, 0, len(arr) - 1))   # 3
print(binary_search(arr, 4, 0, len(arr) - 1))   # -1

Quando usar recursão em vez de iteração

A recursão é excelente quando o problema se decompõe naturalmente em subproblemas menores do mesmo tipo (árvores, divisão e conquista, retrocesso). A iteração é preferível quando: a profundidade da recursão é grande (com risco de estouro da pilha em Python, que por padrão é de aproximadamente 1000), as versões recursiva e iterativa são igualmente claras ou o problema é um laço simples (factorial, Fibonacci sem memoização).

Uma boa regra prática: se desenhar uma árvore de recursão parecer natural, use recursão. Se a árvore for uma linha reta (recursão em cauda), converta para iteração.

import sys

# Python's default recursion limit
print('Recursion limit:', sys.getrecursionlimit())  # 1000

# A list of 2000 elements would overflow the recursive sum_list
# Use iteration for safety:
def sum_list_iter(lst):
    total = 0
    for x in lst:
        total += x
    return total

big = list(range(2000))
print(sum_list_iter(big))  # 1999000 — no stack overflow

Verificação rápida

Teste sua compreensão dos conceitos de Estruturas de Dados e Algoritmos — Preparação para Entrevistas de Programação apresentados nesta lição.

Recapitulação da lição

Nesta lição, você aprendeu: a estrutura de três etapas é Caso-base (resposta mais simples conhecida), Confiança (suponha que o subproblema esteja resolvido) e Construção (combine o elemento atual com o resultado confiável); escreva primeiro os casos-base e evite rastrear mentalmente árvores completas de chamadas; e use iteração quando a profundidade da recursão oferecer risco de estouro da pilha ou quando as formas recursiva e iterativa forem igualmente claras. A seguir, vamos visualizar detalhadamente a pilha de chamadas.

Perguntas Frequentes

A aula “Estrutura da Recursão: Caso Base, Confiança, Construção” é grátis?

Sim — o texto completo de “Estrutura da Recursão: Caso Base, Confiança, Construção” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Coding Interview Prep, atualize para CoddyKit PRO. O curso de Coding Interview Prep inclui 4 aulas no total.

O que vou aprender em “Estrutura da Recursão: Caso Base, Confiança, Construção”?

Aplique o método de três etapas para escrever soluções recursivas corretas para fatorial, potência e soma de dígitos sem rastrear cada chamada. Você pratica Coding Interview Prep com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Coding Interview Prep?

Nenhuma experiência prévia é necessária. Coding Interview Prep no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.

Quanto tempo leva a aula “Estrutura da Recursão: Caso Base, Confiança, Construção”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Coding Interview Prep?

Sim. Cada aula de Coding Interview Prep inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Estrutura da Recursão: Caso Base, Confiança, Construção
  2. Visualizando a Pilha de Chamadas
  3. Compromissos entre Recursão e Iteração
  4. Memoização: Armazenando Resultados Recursivos em Cache
← Voltar para Coding Interview Prep