当前位置: 首页 > news >正文

剑指offer(c++)-04.从尾到头打印链表

从尾到头打印链表

1. 前景知识

链表应该是面试时被提及最频繁的数据结构。链表的结构很简单,它由指针把若干个结点连接成链状结构。链表的创建、插入结点、删除结点等操作都只需要20行左右的代码就能实现,其代码量比较适合面试。

链表是一种动态数据结构,是因为在创建链表时,无须知道链表的长度。当插入一个结点时,只需要为新结点分配内存,然后调整指针的指向来确保新结点被链接到链表当中。内存分配不是在创建链表时一次性完成,而是每添加一个结点分配一次内存。由于没有闲置的内存,链表的空间效率比数组高。

由于链表中的内存不是一次性分配的,因而我们无法保证链表的内存和数组一样是连续的。因此如果想在链表中找到它的第i个结点,我们只能从头结点开始,沿着指向下一个结点的指针遍历链表,它的时间效率为O(n)。而在数组中,我们可以根据下标在O(1)时间内找到第i个元素。。

2. 链表相关题目(摘自:剑指offer):

面试题5:“从尾到头输出链表”、
面试题13:“在O(1)时间删除链表结点”、
面试题15:“链表中的倒数第k个结点”、
面试题16:“反转链表”、
面试题17:“合并两个排序的链表”、
面试题 37:“两个链表的第一个公共结点”等)
面试题26:“复杂链表的复制”,链表中的结点中除了有指向下一个结点的指针,还有指向任意结点的指针,这就是复杂链表。
面试题27:“二叉搜索树与双向链表”,链表中的结点中除了有指向下一个结点的指针,还有指向前一个结点的指针。这就是双向链表。
面试题45:“圆圈中最后剩下的数字”,把链表的末尾结点的指针指向头结点,从而形成一个环形链表。

3. 题目

面试题5 从尾到头打印链表: 输入一个链表的头结点,从尾到头反过来打印出每个结点的值。链表信息如下:

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/ 
4. 解题方法

解题思想1-递归思想

  1. 递归思想需要明确:递和归
  2. 递:下一结点即 head->next,
  3. 递结束判断条件:if( head == NULL ) return outvalue
  4. 归:返回该节点值即head->val
  5. 建立vector存储返回结点的val,并在每次递归调用后返回该值即return outvalue。
// 递归算法代码如下:
// head: 输入链表头
// outvalue: 返回链表值
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> outvalue;
        if(head == NULL)
            return outvalue;
        outvalue = printListFromTailToHead(head ->next);
        outvalue.push_back(head->val);
        return outvalue;
    }
};

解题思想2-反转链表

  1. 反转链表示例:输入: 1->2->3->4->5->NULL,输出: 5->4->3->2->1->NULL
  2. 需要三个结点变量,1.当前待反转结点tmp,2.正在反转的结点now,3.正在反转结点的前一个结点pre
  3. now = head ,tmp = now->next,now->next = pre,pre = now,now = tmp。 反转链表如图
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        // nullptr:c++11中关键字表示空指针
        ListNode* pre = nullptr; // pre:正在反转结点的前一个结点
        ListNode* now = head;    // now:当前正在反转的结点
        ListNode* tmp = now;     // tmp:还未反转的第一个结点
        while(now){
            tmp = now->next;
            now->next = pre;
            pre = now;
            now = tmp;
        }
        vector<int> outvalue;
        // 正序遍历单链表,将值压入vector,然后输出
        while(pre){
            outvalue.push_back(pre->val);
            pre = pre->next;
        }
        return outvalue;
    }
};

相关文章:

  • 操作系统-02.中断与异常及系统调用
  • 操作系统-03.进程的定义、组成、组织方式、特征
  • 操作系统-04.进程的状态与切换
  • 操作系统-05.进程控制
  • 操作系统-06.进程通信
  • 操作系统-06.线程概念、多线程模型
  • 操作系统-07.处理机调度概念、层次
  • 设计模式-01.面向对象七大设计原则
  • C++面向对象高级开发-01.C++ 类相关解析
  • C++面向对象高级开发-02.堆、栈与内存管理
  • C++面向对象高级开发-03.指针与引用
  • JAVA-IDEA-Tomcat 完美解决乱码
  • Servlet-jsp 依赖库pox.xml配置
  • C语言——指针之间的传递
  • MySQL学习笔记(一)
  • 2017 前端面试准备 - 收藏集 - 掘金
  • CentOS6 编译安装 redis-3.2.3
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • Fabric架构演变之路
  • Java 网络编程(2):UDP 的使用
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • JavaScript学习总结——原型
  • java第三方包学习之lombok
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • oschina
  • React 快速上手 - 07 前端路由 react-router
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 浮动相关
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • ------- 计算机网络基础
  • 使用 Docker 部署 Spring Boot项目
  • 使用Maven插件构建SpringBoot项目,生成Docker镜像push到DockerHub上
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (二)构建dubbo分布式平台-平台功能导图
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (算法)前K大的和
  • (学习日记)2024.01.09
  • *ST京蓝入股力合节能 着力绿色智慧城市服务
  • ./configure,make,make install的作用
  • .Net IOC框架入门之一 Unity
  • .NET 命令行参数包含应用程序路径吗?
  • .NET 事件模型教程(二)
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)
  • .net获取当前url各种属性(文件名、参数、域名 等)的方法
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
  • .net网站发布-允许更新此预编译站点
  • /3GB和/USERVA开关
  • :O)修改linux硬件时间
  • @Autowired注解的实现原理
  • [2016.7.test1] T2 偷天换日 [codevs 1163 访问艺术馆(类似)]
  • [AIGC codze] Kafka 的 rebalance 机制
  • [AX]AX2012 SSRS报表Drill through action
  • [BZOJ 4129]Haruna’s Breakfast(树上带修改莫队)
  • [bzoj1901]: Zju2112 Dynamic Rankings