Skip to content

206.反转链表

一、问题描述

反转一个单链表。

示例:

plaintext
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

二、方案一:迭代法

1、思路

使用迭代法反转链表。迭代法通常涉及三个指针:当前指针 cur、前一个指针 prev 和下一个指针 next。初始时,prevnext 都设置为 nil。然后,我们遍历链表,每次迭代中,将 cur 的下一个节点保存下来,赋值为 next,将 cur 的前一个节点设置为 prev,最后将 cur 移动到 next

2、代码实现

go
func reverseList(head *ListNode) *ListNode {
	var cur = head
	var prev, next *ListNode
	for cur != nil {
		next = cur.Next
		cur.Next = pre

		pre = cur
		cur = next
	}

	return pre
}

3、复杂度分析

  • 时间复杂度:O(n),其中 n 是链表的长度。我们需要遍历整个链表一次。
  • 空间复杂度:O(1),不需要额外的空间。

三、方案二:递归法

1、思路

使用递归法反转链表。递归法的基本思路是:

  • 设置当前节点的下一个节点的指针指向前一个节点。
  • 递归地反转剩余的链表。

2、代码实现

go
func reverseList(head *ListNode) *ListNode {
    // 定义一个辅助函数 reverse,它接受两个参数:
    // prev:前一个节点
    // cur:当前节点
    return reverse(nil, head)
}

func reverse(prev *ListNode, cur *ListNode) *ListNode {
    // 如果当前节点 cur 为 nil,则递归结束,返回前一个节点 prev
    if cur == nil {
        return prev
    }

    // 保存当前节点的下一个节点
    next := cur.Next
    // 将当前节点的下一个节点设置为前一个节点,实现反转
    cur.Next = prev

    // 递归调用 reverse 函数,将 next 作为新的当前节点,prev 作为新的前一个节点
    return reverse(cur, next)
}

3、复杂度分析

  • 时间复杂度:O(n),其中 n 是链表的长度。我们需要遍历整个链表一次。
  • 空间复杂度:O(n),递归调用栈的空间。

四、总结

方案时间复杂度空间复杂度
迭代法O(n)O(1)
递归法O(n)O(n)

迭代法在空间复杂度上更优,而递归法在代码结构上更简洁。选择哪种方法取决于具体的使用场景和个人偏好。

木川工作室 (微信:mcmc2024)