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

总结

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

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

相关推荐
muyierfly11 分钟前
34.贪心算法1
算法·贪心算法
她似晚风般温柔7891 小时前
Uniapp + Vue3 + Vite +Uview + Pinia 分商家实现购物车功能(最新附源码保姆级)
开发语言·javascript·uni-app
Jiaberrr2 小时前
前端实战:使用JS和Canvas实现运算图形验证码(uniapp、微信小程序同样可用)
前端·javascript·vue.js·微信小程序·uni-app
everyStudy3 小时前
JS中判断字符串中是否包含指定字符
开发语言·前端·javascript
luthane3 小时前
python 实现average mean平均数算法
开发语言·python·算法
静心问道3 小时前
WGAN算法
深度学习·算法·机器学习
Ylucius3 小时前
动态语言? 静态语言? ------区别何在?java,js,c,c++,python分给是静态or动态语言?
java·c语言·javascript·c++·python·学习
200不是二百3 小时前
Vuex详解
前端·javascript·vue.js
杰九3 小时前
【算法题】46. 全排列-力扣(LeetCode)
算法·leetcode·深度优先·剪枝
LvManBa3 小时前
Vue学习记录之三(ref全家桶)
javascript·vue.js·学习