🥳每日一练-反转链表-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,然后将遍历到的节点头插法插到新的链表中。这个方法简单,就不展示代码了

总结

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

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

相关推荐
JELEE.2 小时前
Django登录注册完整代码(图片、邮箱验证、加密)
前端·javascript·后端·python·django·bootstrap·jquery
电鱼智能的电小鱼4 小时前
基于电鱼 AI 工控机的智慧工地视频智能分析方案——边缘端AI检测,实现无人值守下的实时安全预警
网络·人工智能·嵌入式硬件·算法·安全·音视频
孫治AllenSun4 小时前
【算法】图相关算法和递归
windows·python·算法
格图素书5 小时前
数学建模算法案例精讲500篇-【数学建模】DBSCAN聚类算法
算法·数据挖掘·聚类
yuuki2332336 小时前
【数据结构】用顺序表实现通讯录
c语言·数据结构·后端
DashVector6 小时前
向量检索服务 DashVector产品计费
数据库·数据仓库·人工智能·算法·向量检索
AI纪元故事会6 小时前
【计算机视觉目标检测算法对比:R-CNN、YOLO与SSD全面解析】
人工智能·算法·目标检测·计算机视觉
夏鹏今天学习了吗6 小时前
【LeetCode热题100(59/100)】分割回文串
算法·leetcode·深度优先
卡提西亚6 小时前
C++笔记-10-循环语句
c++·笔记·算法
还是码字踏实6 小时前
基础数据结构之数组的双指针技巧之对撞指针(两端向中间):三数之和(LeetCode 15 中等题)
数据结构·算法·leetcode·双指针·对撞指针