# 0206. 反转链表 ## 题目地址(206. 反转链表) <https://leetcode-cn.com/problems/reverse-linked-list/> ## 题目描述 反转一个单链表。 ``` <pre class="calibre18">``` 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶: 你可以迭代或递归地反转链表。你能否用两种方法解决这道题? ``` ``` ## 前置知识 - [链表](https://github.com/azl397985856/leetcode/blob/master/thinkings/basic-data-structure.md) ## 公司 - 阿里 - 百度 - 腾讯 - adobe - amazon - apple - bloomberg - facebook - microsoft - snapchat - twitter - uber - yahoo - yelp - zenefits ## 思路 这个就是常规操作了,使用一个变量记录前驱 pre,一个变量记录后继 next. 不断更新`current.next = pre` 就好了 ## 关键点解析 - 链表的基本操作(交换) - 虚拟节点 dummy 简化操作 - 注意更新 current 和 pre 的位置, 否则有可能出现溢出 ## 代码 语言支持:JS, C++, Python,Java JavaScript Code: ``` <pre class="calibre18">``` <span class="hljs-title">/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */</span> <span class="hljs-title">/** * @param {ListNode} head * @return {ListNode} */</span> <span class="hljs-keyword">var</span> reverseList = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">head</span>) </span>{ <span class="hljs-keyword">if</span> (!head || !head.next) <span class="hljs-keyword">return</span> head; <span class="hljs-keyword">let</span> cur = head; <span class="hljs-keyword">let</span> pre = <span class="hljs-params">null</span>; <span class="hljs-keyword">while</span> (cur) { <span class="hljs-keyword">const</span> next = cur.next; cur.next = pre; pre = cur; cur = next; } <span class="hljs-keyword">return</span> pre; }; ``` ``` C++ Code: ``` <pre class="calibre18">``` <span class="hljs-title">/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */</span> <span class="hljs-keyword">class</span> Solution { <span class="hljs-keyword">public</span>: <span class="hljs-function">ListNode* <span class="hljs-title">reverseList</span><span class="hljs-params">(ListNode* head)</span> </span>{ ListNode* prev = <span class="hljs-params">NULL</span>; ListNode* cur = head; ListNode* next = <span class="hljs-params">NULL</span>; <span class="hljs-keyword">while</span> (cur != <span class="hljs-params">NULL</span>) { next = cur->next; cur->next = prev; prev = cur; cur = next; } <span class="hljs-keyword">return</span> prev; } }; ``` ``` Python Code: ``` <pre class="calibre18">``` <span class="hljs-title"># Definition for singly-linked list.</span> <span class="hljs-title"># class ListNode:</span> <span class="hljs-title"># def __init__(self, x):</span> <span class="hljs-title"># self.val = x</span> <span class="hljs-title"># self.next = None</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">reverseList</span><span class="hljs-params">(self, head: ListNode)</span> -> ListNode:</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> head: <span class="hljs-keyword">return</span> <span class="hljs-keyword">None</span> prev = <span class="hljs-keyword">None</span> cur = head <span class="hljs-keyword">while</span> cur: cur.next, prev, cur = prev, cur, cur.next <span class="hljs-keyword">return</span> prev ``` ``` Java Code: ``` <pre class="calibre18">``` <span class="hljs-title">/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{ <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">reverseList</span><span class="hljs-params">(ListNode head)</span> </span>{ ListNode pre = <span class="hljs-keyword">null</span>, cur = head; <span class="hljs-keyword">while</span> (cur != <span class="hljs-keyword">null</span>) { ListNode next = cur.next; cur.next = pre; pre = cur; cur = next; } <span class="hljs-keyword">return</span> pre; } } ``` ``` **复杂度分析** - 时间复杂度:O(N)O(N)O(N) - 空间复杂度:O(1)O(1)O(1) ## 拓展 通过单链表的定义可以得知,单链表也是递归结构,因此,也可以使用递归的方式来进行 reverse 操作。 > 由于单链表是线性的,使用递归方式将导致栈的使用也是线性的,当链表长度达到一定程度时,递归会导致爆栈,因此,现实中并不推荐使用递归方式来操作链表。 1. 除第一个节点外,递归将链表 reverse 2. 将第一个节点添加到已 reverse 的链表之后 > 这里需要注意的是,每次需要保存已经 reverse 的链表的头节点和尾节点 C++实现 ``` <pre class="calibre18">``` <span class="hljs-title">// 普通递归</span> <span class="hljs-keyword">class</span> Solution { <span class="hljs-keyword">public</span>: <span class="hljs-function">ListNode* <span class="hljs-title">reverseList</span><span class="hljs-params">(ListNode* head)</span> </span>{ ListNode* tail = <span class="hljs-params">nullptr</span>; <span class="hljs-keyword">return</span> reverseRecursive(head, tail); } <span class="hljs-function">ListNode* <span class="hljs-title">reverseRecursive</span><span class="hljs-params">(ListNode *head, ListNode *&tail)</span> </span>{ <span class="hljs-keyword">if</span> (head == <span class="hljs-params">nullptr</span>) { tail = <span class="hljs-params">nullptr</span>; <span class="hljs-keyword">return</span> head; } <span class="hljs-keyword">if</span> (head->next == <span class="hljs-params">nullptr</span>) { tail = head; <span class="hljs-keyword">return</span> head; } <span class="hljs-keyword">auto</span> h = reverseRecursive(head->next, tail); <span class="hljs-keyword">if</span> (tail != <span class="hljs-params">nullptr</span>) { tail->next = head; tail = head; head->next = <span class="hljs-params">nullptr</span>; } <span class="hljs-keyword">return</span> h; } }; <span class="hljs-title">// (类似)尾递归</span> <span class="hljs-keyword">class</span> Solution { <span class="hljs-keyword">public</span>: <span class="hljs-function">ListNode* <span class="hljs-title">reverseList</span><span class="hljs-params">(ListNode* head)</span> </span>{ <span class="hljs-keyword">if</span> (head == <span class="hljs-params">nullptr</span>) <span class="hljs-keyword">return</span> head; <span class="hljs-keyword">return</span> reverseRecursive(<span class="hljs-params">nullptr</span>, head, head->next); } <span class="hljs-function">ListNode* <span class="hljs-title">reverseRecursive</span><span class="hljs-params">(ListNode *prev, ListNode *head, ListNode *next)</span> </span>{ <span class="hljs-keyword">if</span> (next == <span class="hljs-params">nullptr</span>) <span class="hljs-keyword">return</span> head; <span class="hljs-keyword">auto</span> n = next->next; next->next = head; head->next = prev; <span class="hljs-keyword">return</span> reverseRecursive(head, next, n); } }; ``` ``` JavaScript 实现 ``` <pre class="calibre18">``` <span class="hljs-keyword">var</span> reverseList = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">head</span>) </span>{ <span class="hljs-title">// 递归结束条件</span> <span class="hljs-keyword">if</span> (head === <span class="hljs-params">null</span> || head.next === <span class="hljs-params">null</span>) { <span class="hljs-keyword">return</span> head; } <span class="hljs-title">// 递归反转 子链表</span> <span class="hljs-keyword">let</span> newReverseList = reverseList(head.next); <span class="hljs-title">// 获取原来链表的第 2 个节点 newReverseListTail</span> <span class="hljs-keyword">let</span> newReverseListTail = head.next; <span class="hljs-title">// 调整原来头结点和第 2 个节点的指向</span> newReverseListTail.next = head; head.next = <span class="hljs-params">null</span>; <span class="hljs-title">// 将调整后的链表返回</span> <span class="hljs-keyword">return</span> newReverseList; }; ``` ``` Python 实现 ``` <pre class="calibre18">``` <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">reverseList</span><span class="hljs-params">(self, head: ListNode)</span> -> ListNode:</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> head <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> head.next: <span class="hljs-keyword">return</span> head ans = self.reverseList(head.next) head.next.next = head head.next = <span class="hljs-keyword">None</span> <span class="hljs-keyword">return</span> ans ``` ``` **复杂度分析** - 时间复杂度:O(N)O(N)O(N) - 空间复杂度:O(N)O(N)O(N) ## 相关题目 - [92.reverse-linked-list-ii](92.reverse-linked-list-ii.html) - [25.reverse-nodes-in-k-groups](25.reverse-nodes-in-k-groups-cn.md) 更多题解可以访问我的LeetCode题解仓库:<https://github.com/azl397985856/leetcode> 。 目前已经37K star啦。 关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。 ![](https://img.kancloud.cn/cf/0f/cf0fc0dd21e94b443dd8bca6cc15b34b_900x500.jpg)