1.背景

大家好,我是酒馆店小二。

力扣206.翻转链表。
题意:反转一个单链表。
示例:
输入: 2->3->4->5->NULL
输出: 5->4->3->2->NULL

2.迭代

如图,

  • 定义pre指针,初始化为 nullptr
  • 定义cur指针,指向头结点;
  • 定义temp指针,指向cur->next节点,为什么要指向这个节点?因为接下来要改变cur->next的指向,将cur->next指向pre;
  • 重复执行上述操作,不断后移precur指针,直到cur指向nullptr,循环结束,链表反转完毕,返回pre指针即可。

说一千道一万,没有代码都不算。

迭代代码:

/*** 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) {}* };*/
ListNode* reverseList(ListNode* head) {ListNode* pre = nullptr;  // 定义 pre 指针,初始化为 nullptr;ListNode* cur = head;  // 定义 cur 指针,指向头结点;while(cur) {ListNode* tmp = cur->next;  // 定义 temp 指针,指向 cur->next 节点cur->next = pre;pre = cur;  // 后移 pre 和 cur 指针cur = tmp;}return pre;
}

3.递归

递归版本稍微复杂一些,其关键在于反向工作。假设链表的其余部分已经被反转,现在应该如何反转它前面的部分?

假设链表为:
n1→…→n k−1→n k→n k+1 →…→n m →∅
若从节点 n k+1 到 n m已经被反转,而我们正处于 n k 。
n1 →…→n k−1 →n k →n k+1 ←…←n m
我们希望 n k+1的下一个节点指向 n k。
所以,nk→next→next = nk。
需要注意的是 n 1的下一个节点必须指向 ∅。如果忽略了这一点,链表中可能会产生环。

ListNode* reverseList(ListNode* head) {if (!head || !head->next) return head;// 递归调用,翻转第二个节点开始往后的链表ListNode* newHead = reverseList(head->next);// 反转头节点与第二个节点的指向head->next->next = head;// head节点指针指为空,因为它已经被它的下一个节点指向了,理论上它就是尾结点// 因为通过递归操作找到的就是尾结点,并且反转尾结点head->next = nullptr;return newHead;
}

4.进阶:反转链表内指定区间

将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n)O(n)O(n),空间复杂度 O(1)O(1)O(1)。
例如:
给出的链表为 1→2→3→4→5→NULL,m = 2,n = 4,
返回 1→4→3→2→5→NULL。

解题思路:

  1. 判断参数 head 是否为空,若空则直接返回;判断m是否等于 n,相等则无需进行操作,直接返回;
  2. 创建一个头结点 dummyHead ,以便对整个链表的操作实现统一;
  3. 指针begin初始化为头节点 dummyHead,begin 将作为待反转链表第一个结点的前驱指针。然后通过变量 i (初始化为 0 )记录当前遍历的结点个数,顺序遍历链表的前 m -1个结点时,begin 不断向前移动,最终指向第 m - 1 个结点;
  4. 指针 start 指向待反转链表的第一个结点,初始化为 begin->next ;指针 finish 指向待反转链表的最后一个结点,初始化为 begin。然后在顺序遍历到第 n 个结点的过程中,finish不断向前移动,直到指向第 n 个结点。
  5. 指针 end 指向待反转链表的最后一个结点的下一个位置;

反转链表:

  • 初始时,指针 pre 指向 start,指针 cur 指向 start->next,begin->next = nullptr,finish->next = nullptr;
  • 反转过程: tmp = cur->next; cur->next = pre;pre = cur;cur = tmp
  • 结束条件:cur == finish
  • 最后一步:将反转后的链表与其余 begin 之前的链表和 end 之后的链表进行连接:
    begin->next = finish; start->next = end;


ListNode *reverseBetween(ListNode *head, int m, int n) {if (!head || m == n) return head;ListNode *dummyHead = new ListNode(-1);dummyHead->next = head;  // 创建链表的头结点ListNode *begin = dummyHead;  // begin 初始化为虚拟头结点int i = 0;while (i < m - 1) {begin = begin->next;  // 循环结束,begin 指向第 m - 1个节点,即待反转链表前一个节点++i;}ListNode *start = begin->next;ListNode *finish = begin;while (i < n) {finish = finsh->next;   // 循环结束,finish 指向第 n 个节点,即待反转链表最后一个节点++i;}ListNode *end = finish->next;  // end 指向待反转链表最后一个节点之后的一个节点ListNode *pre = start;ListNode *cur = start->next;begin->next = nullptr;finish->next = nullptr;while (pre != finish) {ListNode *tmp = cur->next;cur->next = pre;pre = cur;cur = tmp;}begin->next = finish;start->next = end;head = dummyHead->next;delete dummyHead;return head;
}

当时轻别意中人,山长水远知何处。
2022.3.23

C++链表02:反转链表相关推荐

  1. 输入一个链表,反转链表后,输出新链表的表头(ACM格式)(美团面试题)

    输入一个链表,反转链表后,输出新链表的表头 其实这道题就是一个反转链表的题,但是因为自己不会建立链表,所以特地采用ACM的格式试着编写一下,这也美团给我出的一道实习算法题. public class ...

  2. 【算法】输入一个链表,反转链表后,输出新链表的表头。

    题目 输入一个链表,反转链表后,输出新链表的表头. 示例1 输入 {1,2,3} 返回值 {3,2,1} 说明:本题目包含复杂数据结构ListNode Java /* public class Lis ...

  3. 链表之反转链表,万金油的解题方法(java求解)

    链表之反转链表,一招鲜吃遍天(java求解) 内容目录 链表之反转链表,一招鲜吃遍天(java求解) 解题万金油 栗子1:反转整个链表 栗子2:反转某个区间内的链表 栗子3:按照k为一组,反转某个区间 ...

  4. 【剑指Offer专题】链表系列:从尾到头打印链表、反转链表、回文链表、合并两个排序的链表(C++和Python实现)...

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 剑指Offer(三):从尾到头打印链表 输入一个链表的头节点,从尾到头反过来返回每 ...

  5. python反转链表_206. 反转链表(Python)

    题目 难度:★★☆☆☆ 类型:链表 反转一个单链表. 进阶: 你可以迭代或递归地反转链表.你能否用两种方法解决这道题? 示例 输入: 1->2->3->4->5->NUL ...

  6. day03链表基础_移除链表元素_设计链表_反转链表

    链表理论基础 链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思). 链表的入口节点称 ...

  7. Suzy找到实习了吗Day 3 | 链表开始啦 203移除链表元素 707设计链表 206 反转链表

    定义链表的结构 class ListNode:def __init__(self, val, next=None): #构造函数self.val = valself.next = next 尾部nod ...

  8. leetcode链表之反转链表

    本文主要有三道题,都是关于反转链表的算法题,由浅入深. 文章出现的代码都是python3 206.反转链表 题目 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表. 示例1: 输入:h ...

  9. 剑指offer算法题,输入一个链表,反转链表后,输出新链表的表头。

    链表的算法题一直做的浑浑噩噩的,为了避免忘记以及能够及时的温故知新,所以将本次的解答记录如下: 话不多说,先贴代码: /* public class ListNode {int val;ListNod ...

  10. 输入一个链表,反转链表后,输出新链表的表头。

    代码来自Java程序员面试笔试宝典 主要思想: pre   cur   next三个节点 /* public class ListNode {int val;ListNode next = null; ...

最新文章

  1. [bzoj2213][Poi2011]Difference_动态规划
  2. 鸿蒙系统2019发布会,直击丨2019华为开发者大会 “鸿蒙”系统今日正式发布!...
  3. 音视频技术开发周刊 | 203
  4. 软件建模——第3章 项目前期
  5. Sublime Text3常用基本操作
  6. js ---- 对象去重
  7. 推荐12个最好的 JavaScript 图形绘制库
  8. Vue 项目在 IE11 中数据更改后页面数据无变化
  9. 音乐标签编辑器 Meta 2.0.0 for Mac
  10. 开发基于大数据平台的搜索引擎
  11. ORBSLAM关键帧的筛选和插入
  12. 如何通过一个字符串来实例化一个类_Spring官网阅读(一)容器及实例化
  13. 关于GetTickCount函数的用法
  14. 【经验】vmware虚拟机只能使用鼠标无法使用键盘、装VMware-Tools无法复制粘贴的可能解决办法
  15. 一文读懂什么是绿色工厂以及绿色工厂建设细解
  16. MATLAB-三维插值运算
  17. sql注入登陆(菜鸟级)
  18. kibana java_Kibana安装及使用说明
  19. 相册计算机软件,电脑相册制作软件免费版,windows自带安全又免费相册制作软件...
  20. 如何更快地渲染?深入了解3D渲染性能的指南!(5)

热门文章

  1. GIT与SVN的比较
  2. MySQL全版本安装步骤
  3. CNTK API文档翻译(2)——逻辑回归
  4. (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  5. Openlayers 圆的操作
  6. 十个计算机函数,十个常用函数套路
  7. 数据模型与数据库之间的关系
  8. Internet互联网络提供的主要服务
  9. linux基本功系列之wc命令实战
  10. 数字图像处理知识点梳理——第二章 数字图像基础