通常我们在面试中面试官给我们出以下题目:
题目:定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
例如:
为了能够更加清晰的写明解题思路,所以像往常一样,还是用动画去分步解析。
一、问题分析
反转链表,首先想到的是让最后一个结点作为头结点,第一个结点作为尾结点指向 null。
如果我们把指针反方向改变,就可以轻松完成整个链表的反转。
说到改变指针,我们有两个方式,第一种是从前到后改变指针,第二种是从后往前改变指针。从前往后代表迭代方式,从后往前是递归的方式,这个不难理解,直接上动画。
二、动画实现
递归法:
迭代法:
三、解题思路
迭代法
从前到后开始反转,我们需要三个指针,第一个指针指向当前头结点 head,第二个指针指向第二个节点 curP(当前结点),第三个指针为保存下一个节点的临时节点 temp。
1、反转顺序为,先保存下一节点。
2、然后让当前结点的指向前一节点。
3、最后移动当前结点到下一结点。(head 头节点一开始初始化指向 null)。
4、重复该循环。
递归法
递归法只不过换了一个顺序,先递进去,然后在执行以上反转操作。
1、让当前结点的下一节点的下一节点指向当前结点。
2、当前节点的下一结点指向 null,直到递归完毕,完成反转。
四、代码实现
//& 反转链表 - 递归实现
var reverseList = function(curP) {
if(curP == null || curP.next == null) return curP;
var tail = reverseList(curP.next)
curP.next.next = curP
curP.next = null
return tail;
};
//& 反转链表 — 迭代实现
var reverseList = function(head) {
if(head == null || head.next == null) return head;
var curP = head.next
head.next = null
var temp = null
while(curP !== null){
temp = curP.next
curP.next = head
head = curP
curP = temp
}
return head;
}
java
//& 反转链表 - 迭代实现
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null) return null;
ListNode pre = null;
ListNode curP= head;
while(curP != null){
ListNode temp = curP.next;
curP.next = pre;
pre = curP;
curP = temp;
}
return pre;
}
}
//& 反转链表 — 递归实现
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null) return head;
ListNode tail = reverseList(head.next);
head.next.next = head;
head.next = null;
return tail;
}
}
python
//& 反转链表 - 迭代实现
class Solution:
def ReverseList(self, pHead):
if not pHead or not pHead.next:
return pHead
last = None
while pHead:
tmp = pHead.next
pHead.next = last
last = pHead
pHead = tmp
return last
//& 反转链表 — 递归实现
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if not head:
return None
if not head.next:
return head
headNode = self.reverseList(head.next)
head.next.next = head
head.next = None
return headNode
五、性能分析
1、迭代法:
时间复杂度:需要遍历链表的整个长度,由链表长度决定,复杂度为 O(n)。
空间复杂度:需要临时的变量空间,为 O(1)
2、递归法:
时间复杂度:需要遍历链表的整个长度,由链表长度决定,复杂度为 O(n)。
空间复杂度:使用的额外栈空间内存,空间复杂度为 O(n)。
六、测试用例
-
输入空的头结点(null)
-
输入一个节点的链表
-
输入多个节点的链表
作者Info:
【作者】:小鹿
【原创公众号】:小鹿动画学编程。
【简介】:一个喜欢用动画讲解技术的程序员!
【转载说明】:转载请说明出处,谢谢合作!~