【递归、搜索与回溯算法练习】day1

news2025/1/21 0:54:47

文章目录

  • 一、面试题 08.06. 汉诺塔问题
    • 1.题目简介
    • 2.解题思路
    • 3.代码
    • 4.运行结果
  • 二、21. 合并两个有序链表
    • 1.题目简介
    • 2.解题思路
    • 3.代码
    • 4.运行结果
  • 三、206. 反转链表
    • 1.题目简介
    • 2.解题思路
    • 3.代码
    • 4.运行结果
  • 总结


一、面试题 08.06. 汉诺塔问题

1.题目简介

面试题 08.06. 汉诺塔问题
在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制:
(1) 每次只能移动一个盘子;
(2) 盘子只能从柱子顶端滑出移到下一根柱子;
(3) 盘子只能叠在比它大的盘子上。
请编写程序,用栈将所有盘子从第一根柱子移到最后一根柱子。
你需要原地修改栈。
在这里插入图片描述

2.解题思路

首先,通过分析可以知道,这个题目有三种可能出现的情况:

  1. 当A上的元素个数n为1时,直接将A上的元素转移到C;
  2. 当A上的元素个数n为2时,先将A上最上面的1个元素转移到B,再将A上剩余的1个元素转移到C,最后将B上的元素转移到A;
  3. 当A上的元素个数n大于2时,先将A上最上面的n - 1个元素转移到B,再将A上剩余的1个元素转移到C,最后将B上的n - 1个元素转移到A。
    将A上剩余的1个元素转移到C时,此时B上的元素可以放A/C上,相当于将n个元素的问题化简为n-1个元素的问题(只需要将A和B柱子的位置进行交换,就能实现)。

因此,我们可以将问题转化为先将A上n-1个元素转移到B,再将A上剩余的1个元素转移到C,最后将B上的n-1个元素转移到C。

3.代码

class Solution {
public:
    void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {
      dfs(A, B, C, A.size());//这个函数的逻辑就是将A上的元素转移到C上
    }
    void dfs(vector<int>& A, vector<int>& B, vector<int>& C, int n)
    {
      if(n == 1)//A上面只有一个元素的话,将A的元素直接放到C位置
      {
        C.push_back(A.back());
        A.pop_back();
        return;
      }
      dfs(A, C, B, n - 1);//将A上的n-1个元素先转移给B
      //将A上最后一个元素直接移到C上
      C.push_back(A.back());
      A.pop_back();
      dfs(B, A, C, n - 1);//将B上的n-1个元素移动到C
    }
};

4.运行结果

在这里插入图片描述

二、21. 合并两个有序链表

1.题目简介

21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
在这里插入图片描述

在这里插入图片描述

2.解题思路

递归思路:
将两个链表头结点中较小的那个作为最终的头结点进行返回,剩余的节点交给递归。(相当于排除被选中的头结点以后,将新的两个链表进行合并)。
迭代思路:

  1. 先设定一个新的链表头结点 list3 ,用 l3 遍历 list3
  2. 分别用指针 l1 和 l2 去遍历 list1 和 list2 ;
  3. 如果 l1->val < l2->val ,让 l3->next=l1;l1=l1->next;l3=l3->next;
    否则,让 l3->next=l2;l2=l2->next;l3=l3->next;
  4. 直到将两个链表中的一个遍历完,再将另一个链表剩余节点全部拼接到l3的next。
  5. 最终返回list3->next即可。

3.代码

递归:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if(list1 == nullptr) return list2;
        if(list2 == nullptr) return list1;
        if(list1 -> val < list2 -> val) //当l1的当前节点小于l2时,我们就返回l1的这个节点并遍历l1(可能会修改它的next节点)
        {
            list1 -> next = mergeTwoLists(list1 -> next, list2);
            return list1;

        }
        else//同理
        {
            list2 -> next = mergeTwoLists(list1, list2 -> next);
            return list2;
        }
    }
};

迭代:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        ListNode* list3 = new ListNode;
        ListNode* l1 = list1, *l2 = list2, *l3 = list3;
        while(l1 && l2)
        {
            if(l1 -> val < l2 -> val)
            {
                l3 -> next = l1;
                l1 = l1 -> next;
                l3 = l3 -> next;
            }
            else
            {
                l3 -> next = l2;
                l2 = l2 -> next;
                l3 = l3 -> next;
            }
        }
        if(l1)
        {
            l3 -> next = l1;
        }
        else
        {
            l3 -> next = l2;
        }
        return list3 -> next;
    }
};

4.运行结果

递归:
在这里插入图片描述
迭代:
在这里插入图片描述

三、206. 反转链表

1.题目简介

206. 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.解题思路

递归思路
将当前节点之后的链表节点进行逆转,再将当前节点放置到逆转后的链表之后(即,head -> next -> next = head,因为head->next经过逆转此时是逆转后链表的最后一个节点,因此可以直接将head放置到head -> next -> next这个位置)

迭代思路

  1. 双指针法(准确来说是三指针法,两个指针进行逆转,一个指针进行遍历)
  2. 用prev指向原链表中cur的前一个节点,用next指向原链表中cur的后一个节点。
  3. 用prev和cur进行逆转链表,用next遍历链表避免越界(每逆转一次,将prev指向cur,将cur指向next,将next指向next -> next,即往后遍历一个节点)
  4. 直到将链表遍历结束,即next为nullptr。

注意:由于每次逆转都是在循环体内进行,因此当next为空时,cur还有最后一次逆转未完成,因此需要补上

3.代码

递归:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head == nullptr || head -> next == nullptr)
        {
            return head;
        }
        ListNode* newhead = reverseList(head -> next);
        head -> next -> next = head;
        head -> next = nullptr;
        return newhead;
    }
};

迭代:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head == nullptr || head -> next == nullptr) return head;
        ListNode* prev = nullptr;
        ListNode* cur = head;
        ListNode* next = head -> next;
        while(next)
        {
            cur -> next = prev;
            prev = cur;
            cur = next;
            next = next -> next;
        }
        cur -> next = prev;
        return cur;
    }
};

4.运行结果

递归:
在这里插入图片描述
迭代:
在这里插入图片描述


总结

今天是递归、搜索与回溯算法练习的第1天。
良好的开端是成功的一半,加油。
文中题目均来源于Leetcode,小伙伴们可以点击题目简介中的链接进行练习。
如果本篇文章对你有所启发的话,希望可以多多支持作者,谢谢大家!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/813134.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

玩转LaTeX(二)【特殊字符、插图设置、表格、浮动体】

特殊字符&#xff1a; 导言区&#xff1a;&#xff08;添加几个宏包&#xff09; \usepackage{xltxtra} %\XeLaTeX(提供了针对XeTeX的改进并且加入了XeTeX的LOGO)\usepackage{texnames} %LOGO\usepackage{mflogo}\usepackage{ctex} 正文区&#xff1a; \begin{document}…

vue拖拽改变宽度

1.封装组件ResizeBox.vue <template><div ref"resize" class"resize"><div ref"resizeHandle" class"handle-resize" /><slot /></div> </template> <script> export default {name: Resi…

【八】mybatis 日志模块设计

mybatis 日志模块设计 简介&#xff1a;闲来无事阅读一下mybatis的日志模块设计&#xff0c;学习一下优秀开源框架的设计思路&#xff0c;提升自己的编码能力 模块设计 在Mybatis内部定义了4个级别&#xff1a;Error:错误 、warn:警告、debug:调试、trance&#xff0c;日志优…

C++STL序列式容器——vector容器详解

纵有疾风起&#xff0c;人生不言弃。本文篇幅较长&#xff0c;如有错误请不吝赐教&#xff0c;感谢支持。 &#x1f4ac;文章目录 一.vector容器基本概念二.vector常用操作①vector构造函数②特性操作③元素操作④赋值操作⑤交换操作⑥比较操作⑦插入和删除操作 一.vector容器基…

MATLAB编程实践12、13

生命游戏 游戏的宇宙是无限可扩展的二维矩形网格&#xff0c;群体是那些标注为存活的网格的集合。群体可以依照称为代的离散时间步距进化。在每一步中&#xff0c;每个网格的命运由它周围最近的8个网格邻居的活度决定&#xff0c;规则如下&#xff1a; 如果一个存活的网格有两个…

想阻止BOT攻击?一起聚焦灵活有效的F5解决方案

伴随着突如其来的数字创新&#xff0c;使潜在的欺诈无处不在。现在&#xff0c;帮我们查找机票交易、位置理想的演唱会座位的 BOT技术正在为网络犯罪分子所利用。权威数据表示&#xff0c;在过去5年&#xff0c;撞库攻击已成为造成经济损失的最大原因之一&#xff0c;几乎每个企…

小研究 - 基于解析树的 Java Web 灰盒模糊测试(二)

由于 Java Web 应用业务场景复杂, 且对输入数据的结构有效性要求较高, 现有的测试方法和工具在测试Java Web 时存在测试用例的有效率较低的问题. 为了解决上述问题, 本文提出了基于解析树的 Java Web 应用灰盒模糊测试方法. 首先为 Java Web 应用程序的输入数据包进行语法建模创…

前端技术周刊 2023-07-30:Promise.withResolvers 进入 Stage3

项目地址&#xff1a;olivewind/weekly[1] 微信公众号&#xff1a;依赖注入 发布时间&#xff1a;2023.07.30 本周内容&#xff1a;资讯x2、开源x8、文章x4 动态 Promise.withResolvers 进入 Stage3 某些情况下需要在 Promise 外部获取 resolve 和 reject 句柄&#xff0c;我们…

【云原生】一文学会Docker存储所有特性

目录 1.Volumes 1.Volumes使用场景 2.持久将资源存放 3. 只读挂载 2.Bind mount Bind mounts使用场景 3.tmpfs mounts使用场景 4.Bind mounts和Volumes行为上的差异 5.docker file将存储内置到镜像中 6.volumes管理 1.查看存储卷 2.删除存储卷 3.查看存储卷的详细信息…

RWEQ模型参量提取

土壤风蚀是一个全球性的环境问题。中国是世界上受土壤风蚀危害最严重的国家之一&#xff0c;土壤风蚀是中国干旱、半干旱及部分湿润地区土地荒漠化的首要过程。中国风蚀荒漠化面积达160.74104km2&#xff0c;占国土总面积的16.7%&#xff0c;严重影响这些地区的资源开发和社会经…

机器学习深度学习——Dropout

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——权重衰减 &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你们有所帮助 Drop…

【MTI 6.S081 Lab】traps

【MTI 6.S081 Lab】traps RISC-V assembly (easy)Backtrace (moderate)实验任务Hints解决方案backtracesys_sleep Alarm (hard)实验任务test0: invoke handlerHint test1()/test2()/test3(): resume interrupted codeHints 解决方案trap.c中的时钟中断处理程序sys_sigalarmsys_…

大促之前全链路压测监控

1. skywalking服务监控 1.1 skywalking简介 Skywalking 是一个APM系统&#xff0c;即应用性能监控系统&#xff0c;为微服务架构和云原生架构系统设计 它通过探针自动收集所需的指标&#xff0c;并进行分布式追踪&#xff0c;通过这些调用链路以及指标&#xff0c;Skywalking …

使用Postman如何在接口测试前将请求的参数进行自定义处理

1、前言 当我们使用 Postman 进行接口测试时&#xff0c;对于简单的不需要处理的接口&#xff0c;直接请求即可&#xff0c;但是对于需要处理的接口&#xff0c;如需要转码、替换值等&#xff0c;则就麻烦一些&#xff0c;一般我们都是先手动把修改好的值拷贝到请求里再进行请…

计算机的大小端模式

计算机的大小端模式 大端/小端字节序字节序转换函数判断Linux字节序的方法string有字节序的说法吗64位系统和32位系统的区别 大端/小端字节序 计算机硬件有两种储存数据的方式&#xff1a;大端字节序&#xff08;big endian&#xff09;和小端字节序&#xff08;little endian…

MySQL数据库——DQL操作——基本查询

文章目录 前言事前准备——测试数据整表查询指定列查找别名查询MySQL运算符条件查询模糊查询排序查询聚合查询分组查询分组之后的条件筛选 分页查询将整张表的数据插入到另一张表中 前言 MySQL数据库常见的操作是增删查改&#xff0c;而其中数据的查询是使用最多&#xff0c;也…

玩转LaTeX(三)【数学公式(基础)、​矩阵、多行公式】

数学公式基础 导言区&#xff08;引包&#xff09; \usepackage{amsmath} %带星号的eqution 正文区 \begin{document}%数学公式初步 \section{简介} \LaTeX{}将排版内容分为文本模式和数学模式。文本模式用于普通文本排版&#xff0c;数学模式用于数学公式排版。 …

小白带你学习linux的mysql服务(主从mysql服务和读写分离三十一)

目录 二、MySQL Replication优点&#xff1a; 三、MySQL复制类型 1、异步复制&#xff08;Asynchronous repication&#xff09; 2、全同步复制&#xff08;Fully synchronous replication&#xff09; 3、半同步复制&#xff08;Semisynchronous replication&#xff09;…

用pip给python安装第三方包

2023年7月30日&#xff0c;周日晚上 目录 搜索包安装包升级包卸载包查看安装了哪些包查看指定的包的详细信息查看pip把某个包安装到了哪里 搜索包 现在只能去专门的网站搜索python的第三方包了 Search results PyPI 安装包 通过下面这条指令就可以安装包 pip install pac…

【数据分享】1999—2021年地级市工业企业资产情况和主要财务指标(Excel/Shp格式)

在之前的文章中&#xff0c;我们分享过基于2000-2022年《中国城市统计年鉴》整理的1999-2021年地级市的人口相关数据、各类用地面积数据、污染物排放和环境治理相关数据、房地产投资情况和商品房销售面积、社会消费品零售总额和年末金融机构存贷款余额、地方一般公共预算收支状…