💯【算法面试】Go题解 4.反转链表 | 刷题打卡

549 阅读2分钟

个人评价:链表的经典面试题,有必要重提一下~

题目难度:🌟 (参考 LeeCode 简单🌟 、中等🌟 🌟 、困难🌟 🌟 🌟 )

另,通常算法题会考察分析时间复杂度和空间复杂度,可参考笔者之前的文章

「数据结构&算法」必知必会系列:3. 时间 & 空间复杂度(下)

反转链表

题目描述

206.反转链表 | 剑指 Offer 24. 反转链表

反转一个单链表。

示例:

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

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

进阶: 你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

解题思路

方法一

迭代法:按原始顺序迭代,将迭代到的结点依次移为头结点,直至尾结点结束。

Go 代码如下

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */

func reverseList(head *ListNode) *ListNode {
    var prev *ListNode
    curr := head
    for curr != nil {
        next := curr.Next
        curr.Next = prev
        prev = curr
        curr = next
    }
    return prev
}

相对比较基础,前提需熟悉链表结构,且了解指针操作,详细可参考之前的博文:「数据结构&算法」必知必会系列:7. 常见数据结构——链表(下)

复杂度?🙌 时间 O(n) 空间 O(1)

方法二

链表本身具有天然的递归性,反转链表也可使用递归实现,理解起来比迭代多一点难度。

以下动图的图解可适当便于理解,递归反转前面部分链表指向 & 注意下一节点指向null。

  • 使用递归函数,一直递归到链表的最后一个结点,该结点就是反转后的头结点,记作 ret
  • 此后,每次函数在返回的过程中,让当前结点的下一个结点的 next 指针,指向当前节点。
  • 同时让当前结点的 next 指针指向 NULL ,从而实现从链表尾部开始的局部反转
  • 当递归函数全部出栈后,链表反转完成。

作者:huwt 链接:leetcode-cn.com/problems/re…

Golang 实现代码如下:

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseList(head *ListNode) *ListNode {
    if head == nil || head.Next == nil { return head }

    newHead := reverseList(head.Next)
    head.Next.Next = head
    head.Next = nil
    return newHead
}

复杂度?🙌 时间 O(n) 空间 O(n)

总结

反转链表 真的是面试非常喜欢考的,这题看起来简单,但是能用 两种方法 一遍 bug free 也是不容易。


本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情