leetcode每日一题
7月
1833. 雪糕的最大数量
5801. 消灭怪物的最大数量
1418. 点菜展示表
1711. 大餐计数
5792. 统计平方和三元组的数目
274. H 指数
面试题 10.02. 变位词组
6月
1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?
42. 接雨水
206. 反转链表
234. 回文链表
141. 环形链表
474. 一和零
5777. 使数组元素相等的减少操作次数
5776. 判断矩阵经轮转后是否一致
1897. 重新分配字符使所有字符串都相等
752. 打开转盘锁
5781. 删除一个字符串中所有出现的给定子字符串
5789. 你完成的完整对局数
5788. 字符串中的最大奇数
852. 山脉数组的峰顶索引
1894. 找到需要补充粉笔的学生编号
5786. 可移除字符的最大数目
1893. 检查是否区域内所有整数都被覆盖
1899. 合并若干三元组以形成目标三元组
5799. 最美子字符串的数目
5780. 删除一个元素使数组严格递增
5月
342. 4的幂
231. 2 的幂
560. 和为K的子数组
141. 环形链表
1074. 元素和为目标值的子矩阵数量
461. 汉明距离
1190. 反转每对括号间的子串
664. 奇怪的打印机
1787. 使所有区间的异或结果为零(放弃治疗)
1707. 与数组中元素的最大异或值
810. 黑板异或游戏
1035. 不相交的线
692. 前K个高频单词
1738. 找出第 K 大的异或坐标值
993. 二叉树的堂兄弟节点
13. 罗马数字转整数
1442. 形成两个异或相等数组的三元组数目
12. 整数转罗马数字
1269. 停在原地的方案数
1734. 解码异或后的排列
1310. 子数组异或查询
872. 叶子相似的树
vditor使用说明
645. 错误的集合
930. 和相同的二元子数组
5793. 迷宫中离入口最近的出口
5843. 作为子字符串出现在单词中的字符串数目
5832. 构造元素不等于两相邻元素平均值的数组
5851. 找出不同的二进制字符串
5850. 找出数组的最大公约数
5835. 最大方阵和
n个人匹配,两两匹配,匹配多轮
本文档使用 MrDoc 发布
-
+
首页
206. 反转链表
# 题目 ## 206. 反转链表 [https://leetcode-cn.com/problems/reverse-linked-list/](https://leetcode-cn.com/problems/reverse-linked-list/) 给你单链表的头节点 ``` head ``` ,请你反转链表,并返回反转后的链表。 **示例 1:** ``` 输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1] ``` **示例 2:** ``` 输入:head = [1,2] 输出:[2,1] ``` **示例 3:** ``` 输入:head = [] 输出:[] ``` **提示:** - 链表中节点的数目范围是 `[0, 5000]` - `-5000 <= Node.val <= 5000` # 题解 ## 思路 ## 代码 ```javascript /** * Definition for singly-linked list. * function ListNode(val, next) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } */ /** * @param {ListNode} head * @return {ListNode} */ // 递归 // var reverseList = function(head) { // if(!head || !head.next){ // return head; // } // let newHead = reverseList(head.next); // head.next.next = head; // head.next = null; // return newHead; // }; // 迭代 var reverseList = function(head) { // 初始化指针 let pre = null; // 临时变量 let next = null; while(head){ // 保存下一个节点 next = head.next; // 当前节点指向pre head.next = pre; // 修改pre pre = head; // 执行下一个节点 head = next; } return pre; }; ``` ## 官方 ### 利用外部空间 这种方式很简单,先申请一个动态扩容的数组或者容器,比如 ArrayList 这样的。 然后不断遍历链表,将链表中的元素添加到这个容器中。 再利用容器自身的 API,反转整个容器,这样就达到反转的效果了。 最后同时遍历容器和链表,将链表中的值改为容器中的值。 因为此时容器的值是: ``` 5 4 3 2 1 ``` 链表按这个顺序重新被设置一边,就达到要求啦。 当然你可以可以再新创建 N 个节点,然后再返回,这样也可以达到目的。 这种方式很简单,但你在面试中这么做的话,面试官 100% 会追问是否有更优的方式,比如不用外部空间。所以我就不做代码和动画演示了,下面来看看如何用 O(1)*O*(1) 空间复杂度来实现这道题。 ### 双指针迭代 我们可以申请两个指针,第一个指针叫 pre,最初是指向 null 的。 第二个指针 cur 指向 head,然后不断遍历 cur。 每次迭代到 cur,都将 cur 的 next 指向 pre,然后 pre 和 cur 前进一位。 都迭代完了(cur 变成 null 了),pre 就是最后一个节点了。 动画演示如下: ![迭代.gif](/media/202106/2021-06-01_203517.png) 动画演示中其实省略了一个`tmp`变量,这个`tmp`变量会将`cur`的下一个节点保存起来,考虑到一张动画放太多变量会很混乱,所以我就没加了,具体详细执行过程,请点击下面的幻灯片查看。 代码实现: - Java ``` class Solution { public ListNode reverseList(ListNode head) { //申请节点,pre和 cur,pre指向null ListNode pre = null; ListNode cur = head; ListNode tmp = null; while(cur!=null) { //记录当前节点的下一个节点 tmp = cur.next; //然后将当前节点指向pre cur.next = pre; //pre和cur节点都前进一位 pre = cur; cur = tmp; } return pre; } } ``` ### 递归解法 这题有个很骚气的递归解法,递归解法很不好理解,这里最好配合代码和动画一起理解。 递归的两个条件: 1. 终止条件是当前节点或者下一个节点==null 2. 在函数内部,改变节点的指向,也就是 head 的下一个节点指向 head 递归函数那句 ``` head.next.next = head ``` 很不好理解,其实就是 head 的下一个节点指向head。 递归函数中每次返回的 cur 其实只最后一个节点,在递归函数内部,改变的是当前节点的指向。 动画演示如下: ![递归.gif](/media/202106/2021-06-01_203605.png) 代码实现: - Java ``` class Solution { public ListNode reverseList(ListNode head) { //递归终止条件是当前为空,或者下一个节点为空 if(head==null || head.next==null) { return head; } //这里的cur就是最后一个节点 ListNode cur = reverseList(head.next); //这里请配合动画演示理解 //如果链表是 1->2->3->4->5,那么此时的cur就是5 //而head是4,head的下一个是5,下下一个是空 //所以head.next.next 就是5->4 head.next.next = head; //防止链表循环,需要将head.next设置为空 head.next = null; //每层递归函数都返回cur,也就是最后一个节点 return cur; } } ```
czbiao
2021年6月1日 20:36
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
阅读量
次
本站总访问量
次
本站访客数
人次
Markdown文件
分享
链接
类型
密码
更新密码