🥳每日一练-反转链表-JS简易版

今天要分享的内容是反转链表。这是一个很经典的问题,将一个单指针链表从头指向尾的顺序改成从尾指向头

像下面这样:

变成:

问题很清晰,也很简单,我们来看有哪些解法:

准备数据

javascript 复制代码
const data = [1, 2, 3, 4, 5];
const generateList = (data) => {
	const root = { next: null };
	let node = root;
	data.forEach((item) => {
		const temp = { value: item, next: null };
		node.next = temp;
		node = node.next;
	});
	return root.next;
};

const linkList = generateList(data);

上面代码生成了有五个节点的单链表。链表从 1 到 5。

再准备一个输出链表的方法,用来验证链表是否正确

javascript 复制代码
const printLink = (data) => {
	let node = data;
	while (node) {
		console.log(node.value);
		node = node.next;
	}
};

printLink(linkList);
// 1
// 2
// 3
// 4
// 5

没有问题

反转链表

方法一

javascript 复制代码
// 定义一个函数 reverseLink,接收一个链表作为参数
const reverseLink = (linkList) => {
    // 初始化一个节点指针 node 指向链表的头结点
    let node = linkList;
    // 初始化一个空节点指针 pre 指向 null
    let pre = null;
    // 使用 while 循环遍历链表,直到链表为空
    while (node) {
        // 保存当前节点的下一个节点指针 next
        const next = node.next;
        // 将当前节点的下一个节点指针指向 pre
        node.next = pre;
        // 将 pre 指针指向当前节点
        pre = node;
        // 将 node 指针指向下一个节点
        node = next;
    }
    // 返回反转后的链表头结点
    return pre;
};

逻辑比较简单,从头到尾依次遍历,依次让 node 的 next 指针指向 pre,然后 pre 和 node 分别往后挪动一个位置。直到 node 挪成 null,也就是 pre 挪到了链表的最后一个位置,就停止遍历。并且返回反转之后链表的头节点

测试代码:

javascript 复制代码
printLink(reverseLink(linkList));
// 5
// 4
// 3
// 2
// 1

方法二:

还可以用递归的方式来解决:

javascript 复制代码
// 定义一个函数 reverseLink2,接收一个链表作为参数
const reverseLink2 = (linkList) => {
    // 如果链表为空或只有一个节点,直接返回链表
    if (!linkList || !linkList.next) return linkList;
    // 递归调用 reverseLink 函数,直到链表的最后一个节点
    const lastNode = reverseLink(linkList.next);
    // 将链表的下一个节点的下一个节点指针指向当前节点
    linkList.next.next = linkList;
    // 将当前节点的下一个节点指针指向 null
    linkList.next = null;
    // 返回反转后的链表的头结点
    return lastNode;
};

这个方法的构思就比较巧妙。将调整的位置直接从链表的尾部开始,将一个个节点由后指向前。

帮助理解:

  1. 假设我们已经来到了最后一个 node,也就是 linkList == 节点 5,这时候第一个判断会直接将节点 5 返回
  2. 然后我们就回到了上一层调用的第 6 行代码。在这一层 linkList == 节点 4,lastNode 会是节点 5 。 继续往下执行。下面两行代码的作用是将节点 5 的 next 指针指向 4,并且节点 4 的指针指向 null。最后返回节点 5
  3. 然后又回到了上一层调用的第 6 行代码。在这一层 linkList == 节点 3。lastNode 依旧是节点 5 。继续往下执行。下面两行代码的作用是将节点 4 的 next 指针指向 3,并且节点 3 的指针指向 null。最后返回节点 5
  4. 依次类推

测试代码:

javascript 复制代码
printLink(reverseLink2(linkList));
// 5
// 4
// 3
// 2
// 1

方法三

还有种方法,就是遍历 linkList,然后将遍历到的节点头插法插到新的链表中。这个方法简单,就不展示代码了

总结

这篇文章分享了经典的算法--反转链表,文中提供了三种代码编写方式,都不难,代码注释和解释也都很清晰,方便大家理解

你觉得这篇文章怎么样?喜欢就点赞+关注吧

相关推荐
RaaS10012 分钟前
Agent Skills 进了 Linux Foundation:2.8 亿次安装,但装 skill 还没有安全规范
人工智能·算法·架构
码林鼠26 分钟前
flutter状态管理入门教程-Riverpod
开发语言·javascript·flutter
CV爱数码27 分钟前
CT 重建从零开始(五):ASTRA Toolbox 上手——几何、投影器与算法
图像处理·算法·计算机视觉·ct
TunerT_TQ31 分钟前
超立方体Ramsey(openai/math 家族171)H11攻坚日志|D60–D69:Star分组重数、二幂坐标群、奇偶入射语义与Site‑Level候选计数形式化闭环
算法
互影派39 分钟前
分享:Cocos 互动影游一套代码双端分发(Web H5 + Windows/Steam)实践
javascript
Rabitebla1 小时前
【系统性学习笔记】Linux 权限篇(二):文件属性、权限修改与目录权限的底层逻辑
linux·c++·笔记·学习·算法
Amos_Web1 小时前
Markdonw语法
开发语言·前端·javascript
远离UE41 小时前
半拉格朗日学习笔记 动力学 实时渲染
人工智能·算法
全栈项目管理程序猿1 小时前
ArcGIS JS 基础教程(34):体元系列 - 等值面 VoxelIsosurface
前端·javascript
SensorFlow1 小时前
离页埋点:sendBeacon 返回 true,为什么还不能算接收成功
javascript