【递归搜索回溯专栏】专题一递归:汉诺塔

简介: 【递归搜索回溯专栏】专题一递归:汉诺塔


题目来源

本题来源为:

Leetcode 汉诺塔问题

题目描述

在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制:

(1) 每次只能移动一个盘子;

(2) 盘子只能从柱子顶端滑出移到下一根柱子;

(3) 盘子只能叠在比它大的盘子上。

请编写程序,用栈将所有盘子从第一根柱子移到最后一根柱子。

你需要原地修改栈。

算法原理

如何解决汉诺塔问题:

在解决汉诺塔问题之前,我们首先要知道应该如何来解决此问题。我们一般采取举例子的方式来发现规律:

  1. 当n=1时直接将盘子挪动到C柱子

2. 当n=2的时候,需要先将A柱子的第一个盘子挪动到B柱子,然后在将A柱子的第二个盘子移动到C柱子,最后在将B柱子的盘子移动到C柱子,也就是说我们借助了B柱子来实现将盘子转移的过程。

  1. 当n=3时,先将A柱子的第一个盘子和第二个看成一个整体,借助C柱子,使其移动到B柱子**,而这个问题不就是N=2的时候的情况嘛**,此时就可以将第三个盘子移动到C柱子,依次内推,B柱子上的盘子在借助A柱子转移到C柱子上。

    到这我们其实就可以发现规律了:
    当为n时,需要借助n-1次,将最底下的盘子移动到C柱子。然后在借助A柱子将B柱子上的盘子移动到C柱子

为什么用递归:

到这一步,我们就可以考虑用递归了。

因为主问题和我们的子问题是一模一样的。

子问题的子问题也是一模一样的。

如何编写递归代码:

  1. 重复子问题->函数头:
  2. 只关心某一个子问题在干什么->函数体的书写:
  3. 递归的出口:
    当x=1的时候直接转移到Z柱子上。

代码实现

class Solution 
{
public:
    void hanota(vector<int>& A, vector<int>& B, vector<int>& C) 
    {
        //
        dfs(A,B,C,A.size());
    }
    void dfs(vector<int>& a,vector<int>& b,vector<int>& c,int n)
    {
        //递归出口
        if(n==1)
        {
            //直接将A柱子转移到C柱子
            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);
    }
};

其实本题有更简单的做法:

既然是转移,那我们可以直接进行转移:

class Solution 
{
public:
    void hanota(vector<int>& A, vector<int>& B, vector<int>& C) 
    {
        //直接转移
        C=A;
    }
};
相关文章
|
人工智能 机器人 编译器
【C/C++】g++ 与 gcc的区别
【C/C++】g++ 与 gcc的区别
|
10月前
|
SQL 数据可视化 atlas
低空经济新基建!DataV Atlas 如何用大模型玩转空间数据?
阿里云DataV Atlas推出搭载通义千问最新2.5 Max大模型「时空SQL智能小助手」,通过自然语言生成专业SQL,简化空间数据分析流程,助力智慧农田、城市低空交通及应急调度等领域,推动精准决策和智能化管理。零门槛体验空间智能分析革命,开启“会思考的天空网络”新时代。
685 5
低空经济新基建!DataV Atlas 如何用大模型玩转空间数据?
|
11月前
|
机器学习/深度学习 人工智能 数据可视化
《AI与鸿蒙Next:建筑设计可视化的革新力量》
在建筑设计领域,可视化至关重要。人工智能通过快速生成方案、优化材质与纹理、智能照明模拟及细节增强,极大提升了设计效率和质量。鸿蒙Next图形渲染技术则凭借强大的物理渲染引擎、超分与超帧技术、智慧美学构图和多设备协同渲染,使建筑效果更加逼真细腻。两者的结合不仅缩短了设计周期,还增强了沟通协作,拓展了设计创意边界,为建筑设计行业带来了前所未有的变革与机遇。
228 4
|
11月前
|
JavaScript 算法 安全
深度剖析:共享文件怎么设置密码和权限的 Node.js 进阶算法
在数字化时代,共享文件的安全性至关重要。本文聚焦Node.js环境,介绍如何通过JavaScript对象字面量构建数据结构管理文件安全信息,包括使用`bcryptjs`库加密密码和权限校验算法,确保高效且安全的文件共享。通过实例代码展示加密与权限验证过程,帮助各行业实现严格的信息资产管理与协作。
|
前端开发 JavaScript UED
使用JavaScript实现滑动动画的几种方法
使用JavaScript实现滑动动画的几种方法
|
编译器 C++ 开发者
Visual Studio属性表:在新项目中加入已配置好的C++库
通过以上步骤可以确保Visual Studio中新项目成功地加入了之前已配置好的C++库。这个过程帮助开发者有效地管理多个项目中共享的库文件,提升开发效率。
525 0
Anaconda在开始菜单找不到Anaconda command prompt入口
这篇文章提供了解决Anaconda安装后在开始菜单找不到Anaconda command prompt入口问题的步骤,通过运行命令`python .\\Lib\_nsis.py mkmenus`重新创建Anaconda的开始菜单快捷方式。
Anaconda在开始菜单找不到Anaconda command prompt入口
|
Prometheus 监控 Cloud Native
构建高效可靠的Linux服务器监控体系
【4月更文挑战第30天】 在维护企业级Linux服务器的稳定性和性能方面,一个周全的监控体系是至关重要的。本文将探讨如何利用开源工具和实践构建一个高效、灵活且用户友好的监控系统。我们将重点讨论核心组件的选择、配置、报警机制以及数据分析方法,旨在帮助读者打造一个能够实时响应并预防潜在问题的监控环境。
|
监控 数据管理 Shell
Shell脚本编写:自动化监控上网行为软件的数据备份与恢复
在今天的数字时代,监控上网行为软件变得越来越重要。无论您是个人用户还是企业,了解和管理上网行为数据对于网络安全和资源优化至关重要。本文将介绍如何使用Shell脚本编写一个自动化数据备份与恢复系统,用于监控上网行为软件的数据,以及如何自动将这些数据提交到网站。
340 1