【面试题24 反转链表】
难度: 简单
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
Leetcode题目对应位置: 面试题24:反转链表
思路 1:双指针
维护两个指针 i
,j
,和 head
共三个指针共同完成链表反转。三个指针的站位:head -> i -> j
,循环将 i.next
指向 head
,然后 head = i
,i = j
,j = j.next
,也就是依次右移一位,直到 i
为空。
初始化状态:i = head.next
,j = i.next
循环结束条件: 当 i
为空时循环退出,此时head
恰好指向链表最后一个节点
特殊情况处理: 若 head
为空,直接返回;若 head.next
为空,说明链表只有一个节点,不需要反转,直接返回 head;
时间复杂度: O(n)
空间复杂度: O(1)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if not head: return
if not head.next: return head
i = head.next
j = i.next
head.next = None
while i:
i.next = head # 局部反转链表
head = i
i = j
if j: j = j.next
return head
思路 2:递归
使用递归一直向下到链表的末尾,此时末尾节点就是反转后链表的头节点。在返回过程中,通用情况:让当前节点的 next
节点的 next
指针指向当前节点,就完成了局部的反转。但对于头尾节点还需要特别处理:
- 若当前节点是尾节点,则其没有 next 节点,直接将新的头指针指向它即可;
- 若当前节点是头节点,则需要将其原本的指针指向 None。这一操作可以单独对原链表的头节点操作,也可以在回归的每一步都做。
时间复杂度: O(n)
空间复杂度: O(1)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def __init__(self):
self.newHead = None
def reverseList(self, head):
def recur(head):
if not head: return # 递归边界
recur(head.next)
cur = head.next
if cur is None:
self.newHead = head # 对尾节点的特殊待遇
else:
cur.next = head
head.next = None # 主要是头节点需要这一步,但这里每一步回归都做了
return head
recur(head)
return self.newHead