forked from whx123/JavaHome
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
564 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
## 前言 | ||
反转链表是程序员必备的基本素养,经常在面试、笔试的过程中出现。一直觉得反转链表实现代码不是很好理解,决定搬leetcode那道经典反转链表题出来,用十多张图去解析它,希望加深大家对链表反转的理解,谢谢阅读。 | ||
|
||
### leetcode的反转链表原题&答案 | ||
|
||
**题目描述:** 反转一个单链表。 | ||
``` | ||
输入: 1->2->3->4->5->NULL | ||
输出: 5->4->3->2->1->NULL | ||
``` | ||
|
||
**分析:** | ||
|
||
假设存在链表 1 → 2 → 3 → Ø,我们想要把它改成 Ø ← 1 ← 2 ← 3。 | ||
|
||
在遍历列表时,将当前节点的 next 指针改为指向前一个元素。由于节点没有引用其上一个节点,因此必须事先存储其前一个元素。在更改引用之前,还需要另一个指针来存储下一个节点。不要忘记在最后返回新的头引用! | ||
|
||
**代码实现:** | ||
``` | ||
public ListNode reverseList(ListNode head) { | ||
ListNode prev = null; | ||
ListNode curr = head; | ||
while (curr != null) { | ||
ListNode nextTemp = curr.next; | ||
curr.next = prev; | ||
prev = curr; | ||
curr = nextTemp; | ||
} | ||
return prev; | ||
} | ||
``` | ||
|
||
### 图解链表反转代码的实现 | ||
接下来,我们图解以上代码实现,先对以上实现代码加上行号,如下: | ||
``` | ||
public ListNode reverseList(ListNode head) { //1 | ||
ListNode prev = null; // 2 | ||
ListNode curr = head; // 3 | ||
while (curr != null) { //4 | ||
ListNode nextTemp = curr.next; //5 | ||
curr.next = prev; // 6 | ||
prev = curr; //7 | ||
curr = nextTemp; //8 | ||
} | ||
return prev; //9 | ||
} | ||
``` | ||
|
||
#### 第一行代码图解 | ||
|
||
``` | ||
public ListNode reverseList(ListNode head) { //1 | ||
``` | ||
我们顺着题目描述意思,假设链表就有1、2、3个元素吧,后面还跟着一个null,又因为输入是ListNode head,所以这个即将要反转的链表如下: | ||
|
||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701fbe941179b51?w=909&h=245&f=png&s=21126) | ||
|
||
#### 第二行代码图解 | ||
|
||
``` | ||
ListNode prev = null; // 2 | ||
``` | ||
将null赋值给prev,即prev指向null,可得图如下: | ||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701f9da5c94b500?w=216&h=210&f=png&s=7193) | ||
|
||
#### 第三行代码图解 | ||
|
||
``` | ||
ListNode curr = head; | ||
``` | ||
将链表head赋值给curr,即curr指向head链表,可得图如下: | ||
|
||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701fbfcaab4dd99?w=870&h=243&f=png&s=20089) | ||
|
||
|
||
#### 循环部分代码图解 | ||
|
||
``` | ||
while (curr != null) { //4 | ||
ListNode nextTemp = curr.next; //5 | ||
curr.next = prev; // 6 | ||
prev = curr; //7 | ||
curr = nextTemp; //8 | ||
} | ||
``` | ||
循环部分是**链表反转的核心**部分,我们先走一遍循环,图解分析一波。 | ||
|
||
因为**curr指向了head**,**head不为null**,所以进入循环。**先来看第5行:** | ||
``` | ||
ListNode nextTemp = curr.next; //5 | ||
``` | ||
把curr.next 赋值给nextTemp变量,即nextTemp 指向curr的下一节点(即节点2),可得图如下: | ||
|
||
|
||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701ff3466fffa10?w=833&h=240&f=png&s=21780) | ||
|
||
再执行到第6行: | ||
``` | ||
curr.next = prev; // 6 | ||
``` | ||
把prev赋值给curr.next,因为prev初始化化指向null,即curr(节点1)指向了null,链表图解成这样了: | ||
|
||
|
||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701fbd124bde1f2?w=1068&h=263&f=png&s=27349) | ||
|
||
然后我们看执行到第7行 | ||
|
||
``` | ||
prev = curr; //7 | ||
``` | ||
把curr赋值给prev,prev指向curr,图解如下: | ||
|
||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701fc2fc9a7ba5c?w=1091&h=347&f=png&s=35650) | ||
|
||
接着,我们执行到第8行: | ||
|
||
``` | ||
curr = nextTemp; //8 | ||
``` | ||
把nextTemp赋值给curr,即curr指向nextTemp,图解如下: | ||
|
||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701fc5ceadd3e2f?w=1042&h=364&f=png&s=35340) | ||
|
||
至此,第一遍循环执行结束啦,回到循环条件,**curr依旧不为null**,我们继续图解完它。 | ||
|
||
5-8行代码又执行一遍,依次可得图: | ||
|
||
``` | ||
ListNode nextTemp = curr.next; //5 | ||
curr.next = prev; // 6 | ||
prev = curr; //7 | ||
curr = nextTemp; //8 | ||
``` | ||
|
||
执行完```ListNode nextTemp = curr.next; ```后: | ||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701fceea65ac66e?w=1011&h=360&f=png&s=34547) | ||
|
||
执行完```curr.next = prev; ```后: | ||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701fd391ef75c17?w=1108&h=339&f=png&s=35342) | ||
|
||
执行完```prev = curr; ```后: | ||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701fd5ad58277e1?w=1091&h=359&f=png&s=36280) | ||
|
||
执行完```curr = nextTemp;```后: | ||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701fd73f53f1a2b?w=1103&h=346&f=png&s=35454) | ||
|
||
来到这里,发现curr还是不为null,再回到while循环,再执行一遍: | ||
|
||
``` | ||
ListNode nextTemp = curr.next; //5 | ||
curr.next = prev; // 6 | ||
prev = curr; //7 | ||
curr = nextTemp; //8 | ||
``` | ||
依次可得图: | ||
|
||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701fdf5b6532ed5?w=1130&h=340&f=png&s=35491) | ||
|
||
|
||
![](https://user-gold-cdn.xitu.io/2020/2/7/1702007c264eddd4?w=1077&h=320&f=png&s=32820) | ||
|
||
|
||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701fe5ac9b9d1d8?w=1135&h=330&f=png&s=34388) | ||
|
||
![](https://user-gold-cdn.xitu.io/2020/2/7/1701fe66d7971447?w=1137&h=330&f=png&s=34740) | ||
|
||
来到这里,我们发现curr已经为null了,可以跳出循环了。这时候prev指向的就是链表的反转呀,所以第9行执行完,反转链表功能实现: | ||
|
||
``` | ||
return prev; //9 | ||
``` | ||
|
||
### 参考与感谢 | ||
- [LeetCode 官网](https://leetcode-cn.com/problems/reverse-linked-list/solution/) | ||
|
||
|
||
### 个人公众号 | ||
|
||
![](https://user-gold-cdn.xitu.io/2019/7/28/16c381c89b127bbb?w=344&h=344&f=jpeg&s=8943) | ||
|
||
- 如果你是个爱学习的好孩子,可以关注我公众号,一起学习讨论。 | ||
- 如果你觉得本文有哪些不正确的地方,可以评论,也可以关注我公众号,私聊我,大家一起学习进步哈。 |
Oops, something went wrong.