单向链表的反转是一个非常常见的链表类面试题,我在刷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设置为“头结点”。
一次循环的具体过程就是这样。
所以总结一下单链表的反转:
- 保存当前头结点的下个节点。
- 将当前头结点的下一个节点指向“上一个节点”,这一步是实现了反转。
- 将当前头结点设置为“上一个节点”。
- 将保存的下一个节点设置为头结点。
这样说起来确实有点拗口,但是我推荐大家在做链表类题目和理解链表的具体行为时,用一张纸和笔来辅助自己写写画画,相信很快你就会弄懂链表的具体思路的。