反转链表
题目
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL
进阶:
你可以迭代或递归地反转鍊表。你能否用两种方法解决这道题?
迭代法
从头开始,逐一反转节点。链表的反转本质上是节点之间的链接反转。每个链接关联两个节点,所以每个链接的反转都需要两个节点参与。
假设要反转previous
和current
之间的链接,
- 将
current
指向previous
- 因为要迭代处理所有链接,所以需要一个变量
next
去持有current
下一个节点
举个例子,反转链表1->2->3->4->5
。
首先,previous
指向第一个节点,current
指向第二个节点,next
指向第三个节点。
然后,将current
指向previous
。
再然后,previous, current, next
的指向一起向后移一位。
重复相同的操作,将current
指向previous
。
把previous, current, next
的指向一起向后移一位。
将current
指向previous
。
把previous, current, next
的指向一起向后移一位。
将current
指向previous
。
代码
复杂度分析
时间复杂度
本演算法遍历了一次链表,时间复杂度为:
空间复杂度
使用了三个变量pevious, current, next
。空间复杂度:
递归法
递归法的一般行式就是把一个问题拆分为一个「小问题」和「其余问题」,然后分别解决一个「小问题」和「其余问题」,最后将结果归併起来。而解决「其余问题」的方法依旧是「拆分为一个小问题和其余问题」,直至「其余问题」与「小问题」一样小。
反转链表问题可以拆分为:
- 第一个节点
其余链表
先把「其余链表」反转,再把第一个节点接到反转后的「其余链表」的末尾即可。而「其余链表」可以继续拆分,直至仅包含一个元素为止。
举个例子,反转链表
1->2->3->4->5
。
将其拆分为第一个元素和其余链表。
反转其余链表。将「其余链表」拆分为第一个元素和其余链表。
反转其余链表。将「其余链表」拆分为第一个元素和其余链表。
反转其余链表。将「其余链表」拆分为第一个元素和其余链表。
其余链表仅包含一个元素。复杂程度等同于一个「小问题」。可直接解决(其实就是什么都不做,仅包含一个元素的链就是自身的反向链表)。
然后,归併解。将第一个元素接到已反转的其余链表末尾。
归併解,将第一个元素接到已反转的其余链表末尾。
归併解,将第一个元素接到已反转的其余链表末尾。
归併解,将第一个元素接到已反转的其余链表末尾。
代码
复杂度分析
时间复杂度
本演算法对链表中每一个链接做了一次拆分和一次解归併。时间复杂度是:
空间复杂度
使用了三个变量first, reversedHead, remainReversedTail
。空间复杂度为: