反转单向链表

单向链表的反转是一个非常常见的链表类面试题,我在刷leetcode的过程中,发现了有许多链表题目的解法,都是以反转链表为基础进行的。所以我觉得有必要记录一下。

首先先用一张图来理解单链表的反转。

单链表的反转,就如上图一样,而单链表的反转也有几种方式,今天我主要是想记录我用得最频繁的迭代的方式。

先来看一下链表节点的定义:

public class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; }
}

这就是最基础的一个链表节点,而反转链表的代码,其实非常的短,关键点就在于理解这几行代码究竟让链表产生了什么变化。

public ListNode reverseList(ListNode head) {
    ListNode next = null;
    ListNode pre = null

    while (head != null) {
        next = head.next;
        head.next = pre;
        pre = head;
        head = next;
    }
    return pre;
}

我们可以看到四行代码:

next = head.next; // 1

head.next = pre;  // 2

pre = head;       // 3

head = next;      // 4

第一行代码:next = head.next; 将head.next赋值给next变量,也就是说next指向了节点2,先将节点2保存起来。

第二行代码: head.next = pre; 将pre变量赋值给了head.next,即节点1指向了null。

第三行代码: pre = head; 将head赋值给了pre,即pre指向节点1,将节点1设为“上一个节点”。

第四行代码:head = next; 将next赋值给head,即head指向了节点2。将节点2设置为“头结点”。

一次循环的具体过程就是这样。

所以总结一下单链表的反转:

  • 保存当前头结点的下个节点。
  • 将当前头结点的下一个节点指向“上一个节点”,这一步是实现了反转。
  • 将当前头结点设置为“上一个节点”。
  • 将保存的下一个节点设置为头结点。

这样说起来确实有点拗口,但是我推荐大家在做链表类题目和理解链表的具体行为时,用一张纸和笔来辅助自己写写画画,相信很快你就会弄懂链表的具体思路的。

Search

    Table of Contents