[LeetCode206. 反转链表] | 刷题打卡

224 阅读2分钟

一、题目描述:

反转一个单链表。

示例:

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

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

二、思路分析:

这题非常高频。如果面试的时候遇到做不出来好像很丢人的样子。。。

看题中提示,这题一般有两种解法,递归和迭代。所谓递归和迭代的在翻转数组时变换的差别在于,是从head开始翻转,还是从tail开始翻转。

先说递归,这是从后向前的翻转,先变换尾结点的next,再逐步向前。如果照这个思路去想就很简单了。

  • 想要翻转链表,是不是把当前结点后面的结点指向当前结点就可以了?
  • 怎么获取后面的结点?注意,这里是后面结点翻转后的状态,直接递归调用reverseList(head.next),然后通过head.next获取
  • head.next指向自己
  • 然后head指向null

这里为什么head会指向空?因为用递归的方式是从后向前的,当前结点head应该指向前驱结点的,但是在当前的递归嵌套中还处理不了前驱结点,所有要指向null

再说迭代法。相比较递归,这种翻转是从前向后的,不过要注意的是一次迭代只处理一个指向的翻转,不要想太多,只处理一个,让当前结点指向前驱就可以了,然后同时将当前结点和前驱向后滚动。具体步骤看代码。

三、AC 代码:

class Solution {
    fun reverseList(head: ListNode?): ListNode? {
        return solution2(head)
    }

    // 迭代
    fun solution2(head: ListNode?): ListNode? {
        var prev: ListNode? = null
        var current: ListNode? = head

        while (current != null) {
            var next = current.next
            current.next = prev
            prev = current
            current = next
        }

        return prev
    }

    // 递归
    fun solution1(head: ListNode?): ListNode? {
        if (head?.next == null) {
            return head
        }
        var p = solution1(head.next)
        head?.next?.next = head
        head.next = null
        return p
    }
}

四、总结:

之前做过的题,现在再拿过来做还是会忘记,希望能多做几遍真正掌握链表操作

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