反转链表这题真的是面试非常喜欢考的了,这题看起来简单,但是能用两种方法一遍 bug free 也是不容易的,面试的时候可以筛下来一大批人,无论是对 junior 还是 senior 面试都很爱考。

今天齐姐就带你梳理清楚思路,思路清楚了才能写码如有神

题目


这是从力扣中文站上截下来的,但是这个输出不太形象。

对链表的反转,并不是要把它实际翻个个,只是动一动 next 指针就好了。

什么意思呢?

我们先看对数组进行反转。

数组是一个物理上连续存储的数据结构,反转之后原来放 1 的位置就变成了放 5.


但是链表并不是,因为链表在物理上是不连续的,它的每个单元 ListNode 是通过 next 指针连接在一起的,而每个 ListNode 之间在内存里并不一定是挨着的。

所以反转链表,就不是非要把 1 的位置放 5,因为它们想在哪在哪。

那么怎么保证这个顺序呢?

  • 就是 next 指针。

沿着 next 指针的方向走下去,就是链表的顺序。这也就保证了,只要我们拿到了头节点,就掌控了整个 LinkedList.

那么题目中的例子,形象点是这个样子滴:


也就是元素自己不用动,只需要动动小指针,就是反转了。

递归解法

递归的三步骤大家还记得吗?

Base case + 拆解 + 组合

不记得的赶紧在公众号内回复「递归」二字,获取递归的入门篇详解。

那么我们来看这个题的:

base case:

当只有一个 node,或者没有 node 了呗,也就是

if(node == null || node.next == null) {  return node;}

其实呢,只剩一个 node 的时候严格来讲并不是 base case,而是 corner case,

因为它本可以再 break down 到 node == null 的,但因为后面有对 node.next 的 dereference 操作,所以不能省略。

拆解:

递归的拆解就是把大问题,分解成小一点点的问题,直到 base case 可以返回,进行第三步的组合。

那么这里就是


组合:

组合的意思是,假设我们能够拿到小问题的解,那么用小问题的解去构造大问题的解。

那么这个问题里如何构造呢?


这里很明显,在 2 后面接上 1 就行了,但是怎么拿到 2 呢?

别忘了,原问题里,此时还有 1 指向 2 呢~

也就是 node1.next = node2

然后把 2 指向 1:node2.next = node1

合起来就是:node1.next.next = node1

思路清楚就不绕,看着觉得绕的就是没想清楚哼~

代码

递归的代码写起来都很简洁:

class Solution {    public ListNode reverseList(ListNode head) {        if(head == null || head.next == null) {            return head;        }        ListNode newHead = reverseList(head.next);        head.next.next = head;        head.next = null;        return newHead;    }}

时间复杂度

我们在「递归」这篇文章里说过,递归的时间复杂度分析方法就是把递归树画出来,每个节点的时间加起来就行了。


这个递归树是一个很简单的单项链表,每个节点上做的就是那三行代码,也就是「组合」做的事,即 O(1) 的时间,总共有 n 个节点,那么总的时间就是 O(n).

空间复杂度

那看递归树也很明显了,每一层也就用了点小变量,是 O(1),所以总的空间共是 O(n).

Iterative 解法

(谁能告诉我这个中文的专业说法。。

Iterative 的思路就是:
过一遍这个 Linked List,边过边把这个 node 的 next 指针指向前面那个 node,直到过完全部。

这样说太抽象,面试时也是,直接过例子。


那也就是把 1 的 next 指针翻过来指向 NULL;
把 2 的 next 指针翻过来指向 1;
把 3 的 next 指针翻过来指向 2;
...

所以我们还需要一个变量来记录当前 node 的前一个 node,不妨设为 prev.

同时呢,一旦我们把指针翻转过去,后面的那个 node 就丢了有木有!所以还需要有个额外的变量事先记录下后面的 node,设为 nxt,这样才不至于走丢~

Step1.

翻转箭头:把 1 的 next 指针指向 NULL;



这样子,同时我们也明确了,prev 的初始化应该是 NULL.

然后把这仨变量都移动到下一个位置:


Step2.

翻转箭头:把 2 的 next 指针指向 1,


然后三人行:


Step3.

翻转箭头:把 3 的 next 指针指向 2,


再齐步走:


Step4.

再把 4 的反过来:


再往后走:


Step5.

再把 5 的 next 反过来:


但是因为我们的 while 循环包含了

「翻转箭头」+「三人行」

两个步骤,所以还需要走完最后一个三人行,变成:


很多同学搞不清楚这个 while 循环的结束条件,其实很简单,你就走个例子画画图嘛!

那结束条件就是 curr = null 的时候,
最后返回的是 prev.

好了,看代码吧:

class Solution {    public ListNode reverseList(ListNode head) {        ListNode prev = null;        ListNode curr = head;

        while(curr != null) {            ListNode nxt = curr.next;            curr.next = prev; // 翻转箭头            prev = curr; //三人行            curr = nxt; //三人行        }

        return prev;    }}

时间复杂度

这里的时间复杂度很明显了,就是过了一遍这个链表,所以是 O(n).

空间复杂度

空间是 O(1).




如果你喜欢这篇文章,记得给我点赞留言哦~你们的支持和认可,就是我创作的最大动力,我们下篇文章见!

我是小齐,纽约程序媛,终生学习者,每天晚上 9 点,云自习室里不见不散!

更多干货文章见我的 Github: https://github.com/xiaoqi6666/NYCSDE

不可不会的「反转链表」问题相关推荐

  1. java宋江,Java编程内功-数据结构与算法「单链表」,

    package com.structures.linkedlist; public class SingleLinkedListDemo { public static void main(Strin ...

  2. 「数据结构 | 链表」单链表、双向链表节点操作演示动画

    目录 1. 什么是链表 2. 链表数据结构 2.1 单链表数据结构(Java) 2.2 双向链表数据结构(Java) 3. 单链表操作动画 3.1 新增节点 3.2 删除节点 4. 双向链表操作动画 ...

  3. FXCM福汇外汇 fx-aisa.com「连续走势」与「反转走势

    「连续走势」与「反转走势」是「道氏理论」与「酒田战法」的基础,今天先就这个话题作个简单介绍: 1. 连续走势:连续走势指的是行情走势处于持续的上升或持续的下跌,这是我们真正能够赚到大钱的地方,但是人性 ...

  4. 不带头节点的链表有哪些缺点_23张图!万字详解「链表」,从小白到大佬!

    链表和数组是数据类型中两个重要又常用的基础数据类型. 数组是连续存储在内存中的数据结构,因此它的优势是可以通过下标迅速的找到元素的位置,而它的缺点则是在插入和删除元素时会导致大量元素的被迫移动,为了解 ...

  5. 下标要求数组或指针类型_算法一看就懂之「 数组与链表 」

    数据结构是我们软件开发中最基础的部分了,它体现着我们编程的内功.大多数人在正儿八经学习数据结构的时候估计是在大学计算机课上,而在实际项目开发中,反而感觉到用得不多. 其实也不是真的用得少,只不过我们在 ...

  6. java 链表反转_面试必备 | 不可不会的反转链表

    反转链表这题真的是面试非常喜欢考的了,这题看起来简单,但是能用两种方法一遍 bug free 也是不容易的,面试的时候可以筛下来一大批人,无论是对 junior 还是 senior 面试都很爱考.今天 ...

  7. 算法一看就懂之「 数组与链表 」

    数据结构是我们软件开发中最基础的部分了,它体现着我们编程的内功.大多数人在正儿八经学习数据结构的时候估计是在大学计算机课上,而在实际项目开发中,反而感觉到用得不多. 其实也不是真的用得少,只不过我们在 ...

  8. 06 |「链表」必刷题

    前言 前言:刷「链表」高频面试题. 文章目录 前言 一. 基础回顾 1. 增删改查 2. 虚拟头节点 1)头节点 2)为什么需要虚拟头结点 3. 链表的遍历 二. 高频面试题 1. 例题 例题1:Le ...

  9. 看动画轻松理解「链表」实现「LRU缓存淘汰算法」

    作者 | 程序员小吴,哈工大学渣,目前正在学算法,开源项目 「 LeetCodeAnimation 」5500star,GitHub Trending 榜连续一月第一. 本文为 AI科技大本营投稿文章 ...

  10. 一口气搞懂「链表」,就靠这20+张图了

    顺序存储和链式存储 数组-顺序存储 数组作为一个顺序储存方式的数据结构,可是有大作为的,它的灵活使用为我们的程序设计带来了大量的便利: 但是,但是,数组最大的缺点就是我们的插入和删除时需要移动大量的元 ...

最新文章

  1. wps中的相交_PPT中最好用的一个功能,非它莫属了~
  2. 经典的 Fork 炸弹解析
  3. Android深度探索(卷1)HAL与驱动开发第六章总结
  4. 我的世界手动选择java_如何选中路径-我的世界怎么选择java路?我的世界怎么选择java路径 爱问知识人...
  5. 微信h5网页关闭分享以及关闭当前页面
  6. fck java_FCkjava三种调用方法
  7. Python判断变量类型
  8. Android在线更新安装包,Android在线更新下载方案
  9. qq 实现连接内网_如何穿透内网稳定进行远程桌面?花生壳盒子来搞定
  10. “RPC好,还是RESTful好?”,这个问题不简单!
  11. 惠普HP Laser 107a 打印机驱动
  12. 一名优秀的数据分析师应该具备这10项关键技能
  13. PPT进行图片的背景去除以及填充新背景,保存图片为PDF
  14. 一维条码之code93码的生成和打印
  15. 【OpenCV】障碍物提取
  16. mysql mdf ldf_mdf和ldf是什么文件
  17. 【报告分享】 2020年汽车产销数据及汽车工业运行情况-中国汽车工业协会(附下载)
  18. 系统即将关机请保存关机是由nt_Win7旗舰版系统下开机提示自动关机是由NT AUTHORITY SYSTEM初始如何解决...
  19. 逝去的2009(四)
  20. 帕斯卡计算机介绍,帕斯卡计算机:第一台被写入百科全书的计算机

热门文章

  1. Javascript中Promise对象
  2. 电商“论贱”血拼 传统书店该何去何从
  3. 微信小游戏Laya引擎声音Bug的解决方案
  4. java开发用win7好还是win10_win7和win10系统哪个好用
  5. 如何使用Blender制作360度全景图和全景视频?
  6. 数据库-数据模型(分类、三要素、概念)
  7. 武汉大学计算机 韩立,文澜学术系列讲座 第135期 武汉大学经济与管理学院韩立宁老师:“Financial Network and Industry Connectedness”...
  8. 银河麒麟V10-sp1服务器操作系统桌面环境安装
  9. 无线广播风暴问题定位分析(omnipeek工具)
  10. Oracle LOB 详解