【LeetCode】递归精选8题——基础递归、链表递归

本文详细介绍了递归在解决基础问题如斐波那契数、爬楼梯、汉诺塔、快速幂以及链表操作(如合并、反转和两两交换)中的应用,同时对比了递归和迭代求解的优劣,重点讲解了递归的基本原理和常见问题的解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

基础递归问题:

1. 斐波那契数(简单)

1.1 递归求解

1.2 迭代求解

2. 爬楼梯(简单)

2.1 递归求解

2.2 迭代求解

3. 汉诺塔问题(简单)

3.1 递归求解

4. Pow(x, n)(中等)

4.1 递归求解

4.2 迭代求解

链表递归问题:

1. 合并两个有序链表(简单)

1.1 递归求解

1.2 迭代求解

2. 反转链表(简单)

2.1 递归求解

2.2 迭代求解

3. 两两交换链表中的节点(中等)

3.1 递归求解

3.2 迭代求解

4. 合并 K 个升序链表(困难)

4.1 递归求解

4.2 迭代求解


在解决一个规模为n的问题时,如果满足以下条件,我们可以使用递归来解决:

  1. 问题可以被划分为规模更小的子问题,并且这些子问题具有与原问题相同的解决方法。
  2. 当我们知道规模更小的子问题(规模为n-1)的解时,我们可以直接计算出规模为n的问题的解。
  3. 存在一种简单情况,或者说当问题的规模足够小时,我们可以直接求解问题。

一般的递归求解过程如下:

  1. 验证是否满足简单情况。
  2. 假设较小规模的问题已经解决,解决当前问题。

上述步骤可以通过数学归纳法来证明。

基础递归问题:

1. 斐波那契数(简单)

1.1 递归求解

重复的子问题——函数头设计

int fib(int n)

子问题在做什么——函数体设计

fib(n - 1) + fib(n - 2)

递归出口

fib(0) = 0

fib(1) = 1

class Solution {
public:
    int fib(int n) {
        if (n <= 1)
            return n;

        return fib(n - 1) + fib(n - 2);
    }
};

1.2 迭代求解

递归算法在计算时存在着大量的重复计算,执行效率低,n值稍大时非常耗费时间。斐波那契数列用迭代算法更高效。

class Solution {
public:
    int fib(int n) {
        if (n <= 1)
            return n;

        int a = 0;
        int b = 1;
        int c = 0;
        for (int i = 2; i <= n; i++)
        {
            c = a + b;
            a = b;
            b = c;
        }
        return c;
    }
};

2. 爬楼梯(简单)

2.1 递归求解

重复的子问题——函数头设计

int climbStairs(int n)

子问题在做什么——函数体设计

如果先走1级台阶,还剩n - 1级台阶,有climbStairs(n - 1)种走法;如果先走2级台阶,还剩n - 2级台阶,有climbStairs(n - 2)种走法。一共的走法:

climbStairs(n - 1) + climbStairs(n - 2)

递归出口

当n == 1时,只有1种走法。

当n == 2时,可以一次走1级台阶,走两次;也可以一次走2级台阶,走一次。所以一共有2种走法。

climbStairs(1) = 1

climbStairs(2) = 2

class Solution {
public:
    int climbStairs(int n) {
        if (n <= 2)
            return n;

        return climbStairs(n - 1) + climbStairs(n - 2);
    }
};

(But这题在LeetCode上用递归会超时o(´^`)o)

可以看出爬楼梯是斐波那契数的应用。

2.2 迭代求解

class Solution {
public:
    int climbStairs(int n) {
        if (n <= 2)
            return n;

        int a = 1;
        int b = 2;
        int c = 0;
        for (int i = 3; i <= n; i++)
        {
            c = a + b;
            a = b;
            b = c;
        }
        return c;
    }
};

3. 汉诺塔问题(简单)

3.1 递归求解

​​

重复的子问题——函数头设计

有三根柱子A、B、C,A柱上有n个盘子,将所有盘子从A柱经B柱全部移到C柱上。

void dfs(int n, vector<int>& A, vector<int>& B, vector<int>& C)

子问题在做什么——函数体设计

该问题可划分成2个自相似问题和1次移动:

  1. 将n-1个盘子从A柱经C柱全部移到B柱上:dfs(n - 1, A, C, B);
  2. 将第n个盘子从A柱移到C柱上:C.push_back(A.back());    A.pop_back();
  3. 将n-1个盘子从B柱经A柱全部移到C柱上:dfs(n - 1, B, A, C);

递归出口

当A柱只剩1个盘子时(即n == 1时),将其从A柱移到C柱上。

C.push_back(A.back());

A.pop_back();

class Solution {
public:
    void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {
        if (A.empty())
            return;
        dfs(A.size(), A, B, C);
    }

private:
    // n个盘子从A经B移到C
    void dfs(int n, vector<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值