持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情
关于算法系列已更新部分文章,后续会陆续增加内容:
【1】 算法之用动态规划实现斐波那契数列
【2】 算法之双指针法的应用
【3】 算法之链表的含义
【4】 算法之移除链表元素
【5】 算法之字符串的括号匹配
反转链表
题目描述:
提供一个单链表的头节点 head
,请你反转链表,并返回反转后的链表
题目位置: 206. 反转链表
示例:
输入: head = [1,2]
输出: [2,1]
实现思路
首先,不考虑定义新链表实现反转(浪费空间)。
由于链表的结构和性质,修改链表的结构实际就是操作各个节点的 next。
所以在这个过程中,只需要改变链表的next指针的指向,就可以直接将链表反转 ,不需要重新定义新链表
有两种思路可以解决而这个问题:
-
递归
-
双指针法
关于双指针前面有介绍过字符串反转方法的实现
这两种方式都是从前往后翻转指针指向
代码实现
- 递归:
var reverse = function(pre, head) {
if(!head) return pre;
const temp = head.next;
head.next = pre;
pre = head
return reverse(pre, temp);
}
var reverseList = function(head) {
return reverse(null, head);
};
- 双指针法:
- 如果头结点不存在或只有一个头节点,返回 head 并结束函数
- 初始化 cur = head(cur指针指向头结点),pre = NULL
- cur 用来改变链表的指向,所以需要预先存储cur.next
- cur.next = pre (指向它的前一个节点,pre初始为空,后面会进行移动)
- pre 向后移动一位(也就是当前cur的位置)
- cur向后移动一位(也就是temp的位置,之前预先存储的cur.next)
- 最后返回 pre 指针,pre指针指向的是原来最后的一个节点,也就是新的头节点
var reverseList = function(head) {
if(!head || !head.next) return head;
let temp = null, pre = null, cur = head;
while(cur) {
temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
// temp = cur = null;
return pre;
};
图解:
初始状态:
到达中间某个节点
最终状态