【算法通关】206. 反转链表——二战

263 阅读2分钟

「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战

刷了400多题,做了七八遍反转链表,几个月之后再做两种方法还是都不会做,我是废物 ;(

——leetcode此题热评

前言

大家好,我是一条,欢迎来到我的算法频道。

只做有趣的算法题,只为面试写算法

Question

206. 反转链表

难度:简单

Solution

这道题刷过一遍,就像评论说的,还是记不住,再战翻转链表。

迭代法

在遍历链表时,将当前节点的 \textit{next}next 指针改为指向前一个节点。由于节点没有引用其前一个节点,因此必须事先存储其前一个节点。在更改引用之前,还需要存储后一个节点。最后返回新的头引用。

递归法

递归版本稍微复杂一些,其关键在于反向工作。假设链表的其余部分已经被反转,现在应该如何反转它前面的部分?

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

Code

/**
 * @author 一条coding
 *    public class ListNode {
      int val;
      ListNode next;
      ListNode() {}
      ListNode(int val) { this.val = val; }
      ListNode(int val, ListNode next) { this.val = val; this.next = next; }
    }
 */
class Solution {
​
    public ListNode reverseList(ListNode head) {
        // 迭代
        // 当前只指针的next指向前一个指针 同时记录当前节点的前一个和后一个。
​
        ListNode prev=null;
        ListNode cur=head;
        // 遍历
        while (cur!=null){
            // 记录下一个节点作为下一次循环
            ListNode next=cur.next;
            // 核心
            cur.next=prev;
            // 交换后当前节点变为下一次循环的饿前一个节点
            prev=cur;
            // 下一次循环
            cur=next;
        }
        // 返回 cur=null
        return prev;
    }
}
​
​

递归

class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode newHead = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return newHead;
    }
}

最后

最后,如果文章对你有帮助。

记得给文章点个赞呀!

也给 一条点个关注!