《C++ 递归、搜索与回溯》第1题:汉诺塔问题

《C++ 递归、搜索与回溯》第1题:汉诺塔问题

🔥个人主页:Cx330🌸

❄️个人专栏:《C语言》《LeetCode刷题集》《数据结构-初阶》《C++知识分享》

《优选算法指南-必刷经典100题》《Linux操作系统》:从入门到入魔

《Git深度解析》:版本管理实战全解

🌟心向往之行必能至


🎥Cx330🌸的简介:


前言:

聚焦算法题实战,系统讲解三大核心板块:“精准定位最优解”——优选算法,“简化逻辑表达,系统性探索与剪枝优化”——递归与回溯,“以局部最优换全局高效”——贪心算法,讲解思路与代码实现,帮助大家快速提升代码能力

目录

前言:

递归,搜索与回溯算法前置知识

1. 汉诺塔

算法原理(递归):

思路:

算法流程:

解法代码(C++):

博主手记(字体还请见谅哈):

结尾:


递归,搜索与回溯算法前置知识

1. 汉诺塔

题目链接:

面试题 08.06. 汉诺塔问题 - 力扣(LeetCode)

题目描述:

题目示例:

算法原理(递归):

思路:

这是一道递归方法的经典题目,我们可以先从最简单的情况考虑:

  • 假设 n=1 ,只有一个盘子,很简单,直接把它从A中拿出来,移到C上;
  • 如果 n=2呢?这时候我们就要借助 B 了,因为先盘子必须时刻都在大盘子上面,共需要3步(为了方便叙述,记A中的盘子从上到下为 1号,2号)
    • 1号盘子放到 B 上
    • 2号盘子放到 C上
    • 3号盘子放到 C 上
      至此,C中的盘子从上到下为 1号,2号。
  • 如果 n>2 呢?这时我们需要用到 n=2 时的策略,将A上面的两个盘子挪到 B 上,再将最大的盘子挪到 C 上 ,最后将 B 上的小盘子挪到 C 上就完成了所有步骤。假如 n=3 时如下图:

因为 A 中最后处理的是最大的盘子,所以在移动过程中不存在大盘子在小盘子上的情况。
则本题可以解释为:

  • 对于规模为 n 的问题,我们需要将 A 柱上的 n 个盘子移动到C柱上。
  • 规模为 n 的问题可以被拆分为规模为 n-1 的子问题:
    • a.将 A 柱上的上面 n-1 个盘子移动到B柱上。
    • b.将 A 柱上的最大盘子移动到 C 柱上,然后将 B 柱上的 n-1 个盘子移动到C柱上。
  • 当问题的规模变为 n=1 时,即只有⼀个盘子时,我们可以直接将其从 A 柱移动到 C 柱
  • 需要注意的是,步骤 2.b 考虑的是总体问题中的 子问题b 情况。在处理子问题的子问题b 时,我们应该将 A 柱中的最上面的盘子移动到 C 柱,然后再将 B 柱上的盘子移动到 C 柱。在处理总体问题的子问题b 时,A 柱中的最大盘子仍然是最上面的盘子,因此这种做法是通用的
算法流程:

递归函数设计:void hanotaa(vector& A, vector& B, vector& C, int n)

  • 返回值:无;
  • 参数:三个柱子上的盘子,当前需要处理的盘子个数(当前问题规模)。
  • 函数作用:将 A 中的上面 n 个盘子挪到 C 中

递归函数流程:

  • 当前问题规模为 n=1 时,直接将 A 中的最上面盘子挪到 C 中并返回
  • 递归将 A 中最上面的 n-1 个盘子挪到 B 中;
  • 将 A 中最上面的⼀个盘子挪到 C 中;
  • 将 B 中上面 n-1 个盘子挪到 C 中
解法代码(C++):
class Solution { public: void dfs(vector<int>& A, vector<int>& B, vector<int>& C,int n) { if(n==1) { C.push_back(A.back()); A.pop_back(); return; } dfs(A,C,B,n-1); C.push_back(A.back()); A.pop_back(); dfs(B,A,C,n-1); } void hanota(vector<int>& A, vector<int>& B, vector<int>& C) { int n=A.size(); dfs(A,B,C,n); } };
博主手记(字体还请见谅哈):

结尾:

汉诺塔问题的递归解法,通过分解问题规模,将n个盘子的移动转化为n-1个子问题。算法核心是将A柱的n-1个盘子暂存B柱,移动最大盘子到C柱,再将B柱盘子移到C柱。并强调递归终止条件(n=1时直接移动),展示了递归思想在经典算法问题中的应用

Read more

DocxFactory: 一个C++操作word的开源库(不依赖office控件)

DocxFactory: 一个C++操作word的开源库(不依赖office控件)

目录 1.简介 2.环境搭建与依赖配置 3.模板设计核心技巧 4.常用场景示例 4.1.示例 1:简单文本替换(基础场景) 4.2.示例 2:动态生成表格(结构化数据场景) 4.3.示例 3:插入图片(含资源场景) 5.高级功能与技巧 6.常见问题与解决方案 7.与其他库的对比 8.总结 1.简介         DocxFactory 是一个专注于处理 Microsoft Word 文档(.docx 格式)的 C++ 库,主要用于动态创建、修改和生成 docx

By Ne0inhk
模板进阶:从非类型参数到分离编译,吃透 C++ 泛型编程的核心逻辑

模板进阶:从非类型参数到分离编译,吃透 C++ 泛型编程的核心逻辑

🔥草莓熊Lotso:个人主页 ❄️个人专栏: 《C++知识分享》《Linux 入门到实践:零基础也能懂》 ✨生活是默默的坚持,毅力是永久的享受! 🎬 博主简介: 文章目录 * 前言: * 一. 非类型模板参数:让模板支持 “编译期常量配置” * 1.1 什么是非类型模板参数? * 1.2 必须遵守的 2 个关键规则 * 二. 模板特化:解决 “特殊类型” 的适配问题 * 2.1 解决 “通用模板失效” 的例子 * 2.2 类模板特化:比函数特化更常用 * 2.2.1 全特化:所有模板参数都确定 * 2.3.2 偏特化:对模板参数做 “条件限制”

By Ne0inhk
《 C++ 点滴漫谈: 三十一 》函数重载不再复杂:C++ 高效调试与性能优化实战

《 C++ 点滴漫谈: 三十一 》函数重载不再复杂:C++ 高效调试与性能优化实战

摘要 本篇博客深入探讨了 C++ 中的函数重载及其调试技巧。首先,介绍了函数重载的基本概念及其在 C++ 编程中的应用,强调了如何通过函数重载提高代码的灵活性和可读性。接着,我们讨论了函数重载的常见问题,如二义性、隐式类型转换和重载版本过多的情况,并提供了有效的调试技巧,包括如何使用编译器错误信息、std::enable_if、__PRETTY_FUNCTION__ 等工具帮助调试。此外,博客还展示了 C++11 及以后版本如何增强函数重载的功能,提升代码效率。通过掌握这些技巧和最佳实践,程序员能够编写更加高效、清晰且可维护的 C++ 代码。 1、引言 在 C++ 中,函数重载(Function Overloading)是泛型编程的重要特性之一,它允许在同一作用域内定义多个具有相同函数名、但参数不同的函数。通过函数重载,C++ 提供了一种灵活且高效的方式,使得程序员能够根据参数的不同类型、个数或顺序调用不同的函数实现,而不需要重复编写类似的代码。 1.

By Ne0inhk
【C++指南】vector(二):手把手教你底层原理与模拟实现

【C++指南】vector(二):手把手教你底层原理与模拟实现

.💓 博客主页:倔强的石头的ZEEKLOG主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏:《C++指南》 期待您的关注 文章目录 * 一、引言 * 二、成员变量 * 三、默认成员函数 * 2.1 默认构造函数 * 2.2 析构函数 * 2.3 拷贝构造函数 * 传统写法 * 现代写法 * 2.4 赋值重载函数 * 传统写法 * 现代写法 * 四、元素访问相关 * 3.1 `[]` 重载(非 `const` 版本) * 3.2 `[]` 重载(`const` 版本) * 五、迭代器相关 * 4.1 迭代器类型声明 * 4.

By Ne0inhk