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

文章目录

一. 力扣 面试题 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);
        }
    }
}
相关推荐
那个村的李富贵9 小时前
CANN加速下的AIGC“即时翻译”:AI语音克隆与实时变声实战
人工智能·算法·aigc·cann
power 雀儿9 小时前
Scaled Dot-Product Attention 分数计算 C++
算法
琹箐10 小时前
最大堆和最小堆 实现思路
java·开发语言·算法
renhongxia110 小时前
如何基于知识图谱进行故障原因、事故原因推理,需要用到哪些算法
人工智能·深度学习·算法·机器学习·自然语言处理·transformer·知识图谱
坚持就完事了10 小时前
数据结构之树(Java实现)
java·算法
算法备案代理10 小时前
大模型备案与算法备案,企业该如何选择?
人工智能·算法·大模型·算法备案
赛姐在努力.11 小时前
【拓扑排序】-- 算法原理讲解,及实现拓扑排序,附赠热门例题
java·算法·图论
野犬寒鸦12 小时前
从零起步学习并发编程 || 第六章:ReentrantLock与synchronized 的辨析及运用
java·服务器·数据库·后端·学习·算法
霖霖总总12 小时前
[小技巧66]当自增主键耗尽:MySQL 主键溢出问题深度解析与雪花算法替代方案
mysql·算法
rainbow688912 小时前
深入解析C++STL:map与set底层奥秘
java·数据结构·算法