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

总结

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

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

相关推荐
拉不动的猪1 分钟前
vue与react的简单问答
前端·javascript·面试
mNinGInG5 分钟前
c++练习
开发语言·c++·算法
纪元A梦30 分钟前
分布式锁算法——基于ZooKeeper的分布式锁全面解析
java·分布式·算法·zookeeper
Panesle1 小时前
广告推荐算法:COSMO算法与A9算法的对比
人工智能·算法·机器学习·推荐算法·广告推荐
月亮被咬碎成星星1 小时前
LeetCode[15]三数之和
数据结构·算法·leetcode
旭久1 小时前
react+antd封装一个可回车自定义option的select并且与某些内容相互禁用
前端·javascript·react.js
阿丽塔~1 小时前
React 函数组件间怎么进行通信?
前端·javascript·react.js
JCBP_1 小时前
数据结构3
服务器·c语言·数据结构·vscode
半盏茶香2 小时前
启幕数据结构算法雅航新章,穿梭C++梦幻领域的探索之旅——堆的应用之堆排、Top-K问题
java·开发语言·数据结构·c++·python·算法·链表
冴羽2 小时前
SvelteKit 最新中文文档教程(17)—— 仅服务端模块和快照
前端·javascript·svelte