算法奇妙屋(二十五)-递归问题

文章目录

一. 力扣 面试题 08.06. 汉诺塔问题

1. 题目解析

我们大多数人接触的第一道递归题目应该就是汉诺塔, 当初给小编难的花了两天搞定, 现在再次看会有新的体会

2. 算法原理

1. 当盘子数为1时, 可以直接放到目标盘子, 一步操作
2. 当盘子数为2时, 小盘子先放在B, 大盘子放在C, 小盘子再放到C, 为三步操作
3. 当盘子数为3时, 将黑色上面的两个盘子看为一个整体, 步骤就简化为了:
第一步: 绿和蓝两个盘子从起始柱子A, 借助辅助柱子C, 移动到目标柱子B
第二步: 最大的盘子从起始柱子A, 直接移动到目标柱子C
第三步: 绿和蓝两个盘子从起始柱子B, 借助辅助柱子A, 移动到目标柱子C
因此3个盘子也可以拆解为三步, 具体两个盘子由辅助柱子移动到目标柱子的过程我们不用考虑, 假设方法一定可以完成我们的要求

4. 当盘子数为n时, 将最底下最大盘子上面的n-1个盘子看为一个整体X, 步骤简化为:
第一步: X从起始柱子A, 借助辅助柱子C, 移动到目标柱子B
第二步: 最大的盘子从起始柱子A, 直接移动到目标柱子C
第三步: X从起始柱子B, 借助辅助柱子A, 移动到目标柱子C
因此n个盘子也可以拆解为三步, 具体n-1个盘子由辅助柱子移动到目标柱子的过程我们不用考虑, 假设方法一定可以完成我们的要求

因此我们可以拆解出子问题->函数头: 一堆盘子n由起始柱子A, 借助辅助柱子B, 移动到目标柱子C -> dfs(n, A, B, C)
分解子问题, 解决一个子问题相当于解决了整个问题:
① n-1个盘子由A借助C移动到B: dfs(int n-1, A, C, B)
② 最大的盘子n由A移动到C: n -> C
③ n-1个盘子由B借助A移动到C: -> dfs(int n-1, B, A, C)
递归结束点(起始点): 2到n个盘子时, 都分为三个步骤, 但是1个盘子时, 就一步直接从起始柱移动到目标柱

3. 代码

java 复制代码
class Solution {
    public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {
        int n = A.size();
        dfs(n, A, B, C);
    }

    void dfs(int n, List<Integer> A, List<Integer> B, List<Integer> C) {
        // 递归出口
        if (n == 1) {
            C.add(A.remove(A.size() - 1));
            return;
        }
        // 第一步
        dfs(n - 1, A, C, B);
        // 第二步
        C.add(A.remove(A.size() - 1));
        // 第三步
        dfs(n - 1, B, A, C);
    }
}

二. 力扣 21. 合并两个有序链表

1. 题目解析

2. 算法原理

3. 代码

bash 复制代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if (list1 == null) {
            return list2;
        }
        if (list2 == null) {
            return list1;
        }
        if (list1.val < list2.val) {
            list1.next = mergeTwoLists(list1.next, list2);
            return list1;
        }else {
            list2.next = mergeTwoLists(list1, list2.next);
            return list2;
        }
    }
}

三. 力扣 206. 反转链表

1. 题目解析

题意简单易懂, 这里不过多赘述

2. 算法原理

3. 代码

java 复制代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode newHead = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return newHead;
    }
}

四. 力扣 24. 两两交换链表中的节点

1. 题目解析

2. 算法原理

3. 代码

java 复制代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode newHead = swapPairs(head.next.next);
        ListNode tmp = head.next;
        head.next.next = head;
        head.next = newHead;
        return tmp;
    }
}

五. 力扣 50. Pow(x, n)

1. 题目解析

实现标准库中的求次幂的方法

2. 算法原理

这里用快速幂算法

3. 代码

java 复制代码
class Solution {
    public double myPow(double x, int n) {
        return n > 0 ? pow(x, n) : 1.0 / pow(x, -n);
    }
    public double pow(double x, int n) {
        if (n == 0) {
            return 1.0;
        }
        double tmp = myPow(x, n / 2);
        if (n > 0) {
            return n % 2 == 0 ? tmp * tmp : x * tmp * tmp;
        }else {
            return n % 2 == 0 ? 1.0 / (tmp * tmp) : 1.0 / (x * tmp * tmp);
        }
    }
}
相关推荐
Remember_9932 小时前
【数据结构】初识 Java 集合框架:概念、价值与底层原理
java·c语言·开发语言·数据结构·c++·算法·游戏
:mnong2 小时前
通过交互式的LLM算法可视化工具学习大语言模型原理
学习·算法·语言模型
Remember_9932 小时前
【数据结构】Java集合核心:线性表、List接口、ArrayList与LinkedList深度解析
java·开发语言·数据结构·算法·leetcode·list
甄心爱学习2 小时前
leetcode打卡
算法·leetcode·职场和发展
dragoooon342 小时前
[hot100 NO.62~67]
算法
你撅嘴真丑2 小时前
求矩阵的两对角线上的元素之和 与 sizeof的大作用
线性代数·算法·矩阵
程序员三明治2 小时前
【面试手撕】如何构造二叉树输入用例?ACM模式,路径总和2解题思路
算法·leetcode·面试·acm·构造二叉树·路径总和
干前端2 小时前
Message组件和Vue3 进阶:手动挂载组件与 Diff 算法深度解析
javascript·vue.js·算法
ゞ 正在缓冲99%…2 小时前
2025.12.17华为软开
java·算法