Reverse Linked List

原题链接Reverse Linked List

逆序一个链表

首先是一个比较容易理解的方法,假设链表为A->B->C->D->E->F

通常在解决与链表有关的额问题时会预设置一个头节点,

设置方法为

ListNode* header = new ListNode(-1);
header->next = head; //head是链表的第一个节点

注:以下将head称为链表的首节点,header称为链表的头节点

这种方法有以下几个好处

  • 设置后链表的首节点(head)的前驱节点不再是nullptr,方便更改链表的首节点
  • 可用于解决链表首节点是空节点的情况
  • 可通过header->next作为最后的结果返回

不过第一种解决方法不需要将头节点(header)的后驱节点设置为首节点(head),作为一般性情况,刚开始的结果链表是空,所以

header->next = nullptr;

获得逆序链表的方法,依次遍历原始链表,每遇到一个节点,就将其插入到header和header->next之间

以A->B->C->D->E->F链表为例

  • 初始时链表为header, nullptr
  • 遇到节点A时header, A, nullptr
  • 遇到节点B时header, B, A, nullptr
  • 遇到节点C时header, C, B, A, nullptr
  • 遇到节点F时header, F, E, D, C, B, A, nullptr

代码比较容易

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode* reverseList(ListNode* head) {ListNode* header = new ListNode(-1);ListNode* cur = head;while(cur){//将cur插入到header和header->next之间ListNode* next = cur->next;cur->next = header->next;header->next = cur;cur = next;}head = header->next;delete header;return head;}
};

当然了,这种方法多少显得有些笨拙,第二种方法看起来就有点,唔,高端

其实可以直接遍历的时候逆序,而不是以插入为主要操作,所以最开始头节点的后驱节点设置成首节点即可

header->next = head; //head是链表第一个节点

此时的链表大概是这个样子

header->A->B->C->D->E->F->nullptr

逆序的思路是,一个一个逆序,即先逆序两个,再逆序三个,…,直到逆序所有节点

逆序两个,即逆序A->B

仅仅是交换位置嘛~额,换个角度看,实际上是将B提到header的后面,此时变为

header->B->A->C->D->E->F->nullptr

逆序三个,即逆序A->B->C

在上一步的基础上,把C提到header的后面,此时变为

header->C->B->A->D->E->F->nullptr

啦啦啦~实际上就是依次将遍历到的节点放在header的后面。其实就是小考虑一小部分,最后由部分到整体(算法思想叫啥来着?)

因为逆序后原链表的首节点(head)变为最后一个节点,所以实际上是将head的下一个节点提到header的后面(注意head->next一直在变)

代码如下

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode* reverseList(ListNode* head) {ListNode* header = new ListNode(-1);header->next = head;ListNode* cur = head;while(cur && cur->next){ListNode* next = cur->next;cur->next = next->next;//将next节点插入到header和header->next之间next->next = header->next;header->next = next;}head = header->next;delete header;return head;}
};

Reverse Linked List II

原题链接Reverse Linked List II

仍然是逆序,但是只逆序第m个节点到第n个节点之间(包括m和n)的节点

所以说上面高端的做法这里就显得比较简洁,不过还是先用第一种方法试一下

首先找到第m-1个节点作为header,然后将遍历到的节点依次插入到header和header->next之间

所以就存在两种情况,一种是在[m, n]范围内的节点,另一种不是

  • 如果节点在[m, n]范围内,就将该节点插入到header和header->next之间
  • 如果节点不在[m, n]范围内,就将节点追加到链表末尾

代码如下

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode* reverseBetween(ListNode* head, int m, int n) {ListNode* header = new ListNode(-1);ListNode* cur = head;ListNode* prev = header;ListNode* reverseHeader = nullptr;int count = 1;while(cur){//在[m, n]之间,prev作为header,将遍历到的节点插入到header和header->next之间//在这个过程中需要保存第m个节点,因为在离开[m, n]区域后,之前第m个节点需要作为prev的新值if(count >= m && count <= n){if(count == m)reverseHeader = cur;ListNode* next = cur->next;cur->next = prev->next;prev->next = cur;cur = next;if(count == n)prev = reverseHeader;}//追加到末尾,不要忘记将prev->next置为nullptrelse{prev->next = cur;prev = cur;cur = cur->next;prev->next = nullptr;}++count;}head = header->next;delete header;return head;}
};

额,终于发现这种方法的不足了(只要从代码长度看就不咋地)

应用第二种方法,原链表中直接逆序,但只需要逆序[m, n]范围内的元素

那么,可以先找到第m个节点,逆序n-m次即可

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode* reverseBetween(ListNode* head, int m, int n) {ListNode* header = new ListNode(-1);header->next = head;n -= m;//prev是第m-1个节点ListNode* prev = header;while(--m)prev = prev->next;//cur是第m个节点ListNode* cur = prev->next;//n已经变为n-mwhile(n--){//prev是第m-1个节点,也是逆序节点集的header节点ListNode* next = cur->next;cur->next = next->next;next->next = prev->next;prev->next = next;}head = header->next;delete header;return head;}
};

这两道题主要是逆序链表问题,对于逆序节点可以依次将遇到的节点提到前面(方法二),这种方法比较高效,代码也少:)

每天一道LeetCode-----逆序链表相关推荐

  1. 链表的各种操作实现 链表逆序 链表排序 有序链表归并 链表存在环的判定

    链表的各种操作实现 链表逆序 链表排序 有序链表归并 链表存在环的判定 链表基本操作实现 c语言版本, 该程序在visual c++ 6.0上调试通过! 本人写该程序完全是为学习交流之用,还望大家多多 ...

  2. 逆序链表--递归思路

    2019独角兽企业重金招聘Python工程师标准>>> 今天同学问的问题,猛然一想,还不太容易想到,记录下吧... #include <iostream>using na ...

  3. c语言递归链表逆序,链表逆序的递归实现

    链表逆序是个很基础的算法,考察的是指针操作和基本数据结构.常规的写法当然是OK的,不过要是还会写出一个递归的链表逆序算法,那别人肯定要给你点个赞了. 1 问题描述 给定一个链表,请将其逆序.即如果链表 ...

  4. 学习笔记——C语言实现单链表的基本操作:创建、输出、插入结点、删除结点、逆序链表

    *************************************************** 更多精彩,欢迎进入:http://shop115376623.taobao.com ****** ...

  5. 逆序链表从m到n位置

    目录 1 逆置整个链表 2 逆置一个链表的m到n位的元素,返回逆置后的头结点 核心步骤 1.如何找到逆置段的开始和结束位置? 2.几个关键位置 3.如何连接逆置后的逆置段 分类讨论 逆置段是否包括逆置 ...

  6. 数据结构_Java_基于 线性表-单链表的初始化、逆序、去重、非递减序列的合并(开辟新链表先整体插入一个链表全部元素,再遍历另外一个链表寻找合适位置插入 、开辟新链表实现舍弃原链表)等操作实现

    写在前面 不久前学习了数据结构线性表-数组-链表的相关知识,用C/C++语言实现了 单链表的系列相关操作 .见往期博客: 数据结构实验2_C语言_基于顺序表的非递减有序表的合并.线性表元素的增.删.改 ...

  7. 【C++】链表反转逆序|建立、删除、修改、插入|linux内核链表与普通链表

    目录 C++实现链表逆序 链表的建立.删除.修改.插入 linux内核链表与普通链表 C++实现链表逆序 实现链表逆序,首先要有一个链表,下面是链表的结构体: typedef struct listn ...

  8. 大厂面试算法系列-如何实现链表的逆序(二)-递归法

    导语   接着上次的内容,上次博客中展示了原地进行单链表的逆序操作,当然除了原地逆序还可以通过递归的方式进行调用操作.下面就来看看通过递归的方式如何进行单链表的逆序操作. 递归法逆序链表   假定原来 ...

  9. 单链表实现一元多项式相加_python面试系列 01如何实现单链表的逆序

    题目介绍 来源:腾讯笔试                         难度系数:★★★☆☆                  考察频率:★★★★☆ 题目描述: 给定一个带头结点的单链表,请将其逆序 ...

最新文章

  1. 一个虚拟机网络的XML描述
  2. OOD知识---对OOA\OOD\OOP思想
  3. golang中的strings.IndexRune
  4. 用复制mysql/data 文件夹 下面的数据库的形式来复制数据库出现的问题
  5. 收藏 | 有没有什么可以节省大量时间的 Deep Learning 效率神器?
  6. 数据的标准化【转载】
  7. pandas 表操作
  8. ubuntu15.04安装wps-office的64位版
  9. 版本设置X:none node Title golang版本错误
  10. 用php上传mysql表文件_php实现上传文件并存储到mysql数据库
  11. PHP面向对象笔记(兄弟连)
  12. 几个免费的IT技能学习视频网站
  13. 解读神书《凤凰项目》,带你跳出DevOps转型的所有坑
  14. 【嵌入式系统—实时操作系统】uC/OS II源码的官网下载
  15. 彩虹秒赞7.8源码破解版(去域名授权) 彩虹云任务系统无任何限制
  16. linux ps2键盘不能用,解决usb鼠标与ps2键盘合用时开机键盘失效
  17. 服务器修改内网IP地址
  18. 计算机为什么有网络凭证,Win10访问局域网中计算机共享文件显示需要网络凭证怎么办?...
  19. echarts 水球示例
  20. 【C#】十大排序算法(动图演示+代码实现)

热门文章

  1. python打开360浏览器_python selenium使用360浏览器出现新皮肤设置怎么办?
  2. 浏览器工作原理与实践学习笔记
  3. Java黑皮书课后题第10章:**10.7(游戏:ATM机)使用编程练习题9.7中创建的Account类来模拟一台ATM级
  4. Java黑皮书课后题第5章:**5.22(金融应用:显示分期还贷时间表)对于给定的贷款额,月支付额包括偿还本金及利息。编写一个程序,让用户输入贷款总额年限利率,然后显示分期还贷时间表
  5. oracle反调试,突破前端反调试--阻止页面不断debugger
  6. java code viewer_Java CodeView类代码示例
  7. AM8不能下任何载附件及所有聊天记录无法登记
  8. How to create a jump server in AWS VPC
  9. firefox加载不来
  10. 介绍几款好用的Web开发管理工具