发布于2021-05-30 12:29 阅读(1679) 评论(0) 点赞(11) 收藏(3)
链表和数组相似,它们都是有序的列表、都是线性结构(有且仅有一个前驱、有且仅有一个后继)。不同点在于,链表中,数据单位的名称叫做“结点”,而结点和结点的分布,在内存中可以是离散的。
在链表中,每一个结点的结构都包括了两部分的内容:数据域和指针域。JS 中的链表,是以嵌套的对象的形式来实现的:
- {
- // 数据域
- val: 1,
- // 指针域,指向下一个结点
- next: {
- val:2,
- next: ...
- }
- }
大概是这个样子:
创建链表结点,咱们需要一个构造函数,大概是这种形式:
- function ListNode(val) {
- this.val = val;
- this.next = null;
- }
-
- const node = new ListNode(1)
- node.next = new ListNode(2)
记住在处理链表问题时:处理链表的本质,是处理链表结点之间的指针关系,也就是next指针。
链表的考点一般分为以下三类:
合成问题:
真题描述:将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有结点组成的。 (leetcode 21)
- /**
- * Definition for singly-linked list.
- * function ListNode(val, next) {
- * this.val = (val===undefined ? 0 : val)
- * this.next = (next===undefined ? null : next)
- * }
- */
- /**
- * @param {ListNode} l1
- * @param {ListNode} l2
- * @return {ListNode}
- */
- var mergeTwoLists = function (l1, l2) {
- let node = new ListNode();
- let cur = node;
- while (l1 && l2) {
- if(l1.val <= l2.val){
- cur.next = l1;
- l1 = l1.next
- } else {
- cur.next = l2;
- l2 = l2.next;
- }
- cur = cur.next
- }
- cur.next = l1 !== null ? l1:l2;
- // 返回node.text 很关键
- return node.next
- };
删除问题:
真题描述:给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。(leetcode 83)
- /**
- * Definition for singly-linked list.
- * function ListNode(val, next) {
- * this.val = (val===undefined ? 0 : val)
- * this.next = (next===undefined ? null : next)
- * }
- */
- /**
- * @param {ListNode} head
- * @return {ListNode}
- */
- // 输入:head = [1,1,2]
- // 输出:[1,2]
- var deleteDuplicates = function (head) {
- let cur = head
- while (cur && cur.next) {
- if (cur.val === cur.next.val) {
- cur.next = cur.next.next
- } else {
- cur = cur.next
- }
- }
- return cur.next
- };
真题描述:给定一个排序链表,删除所有含有重复数字的结点,只保留原始链表中 没有重复出现的数字。(leetcode 82)
- /**
- * Definition for singly-linked list.
- * function ListNode(val, next) {
- * this.val = (val===undefined ? 0 : val)
- * this.next = (next===undefined ? null : next)
- * }
- */
- /**
- * @param {ListNode} head
- * @return {ListNode}
- */
- const deleteDuplicates = function(head) {
- // 极端情况:0个或1个结点,则不会重复,直接返回
- if(!head || !head.next) {
- return head
- }
- let dummy = new ListNode()
- dummy.next = head
- let cur = dummy
- while(cur.next && cur.next.next) {
- if(cur.next.val === cur.next.next.val) {
- let val = cur.next.val
- while(cur.next && cur.next.val===val) {
- cur.next = cur.next.next
- }
- } else {
- cur = cur.next
- }
- }
- // 返回链表的起始结点
- return dummy.next;
- };
一般情况下这类问题的关键时通过双指针法来解决(答案稍微有点复杂,我就不写自己答案了)
提示:第一个问题是一个经典的使用快慢指针来解决的链表问题,可以通过这个问题学习双指针。接下来再来带着双指针的思路来解决反转问题
真题描述:给定一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。(leetcode 22)
真题描述:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。(完全反转 leetcode 203)
真题描述:反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。(局部反转 leetcode 92)
真题描述:给定一个链表,判断链表中是否有环。(判断是否成环 leetcode 141)
提示:解决这类问题的核心是设 标识(flag),两道题的思路都是一样的
- /**
- * Definition for singly-linked list.
- * function ListNode(val) {
- * this.val = val;
- * this.next = null;
- * }
- */
-
- /**
- * @param {ListNode} head
- * @return {boolean}
- */
- var hasCycle = function (head) {
- while (head) {
- if (head.flag) {
- return true
- } else {
-
- head.flag = true;
- head = head.next
- }
- }
- return false
- };
真题描述:给定一个链表,返回链表开始入环的第一个结点。 如果链表无环,则返回 null。(定位环启动 leetcode 142)
带着这个思路解决链表问题,一般的题目应该都能解决
原文链接:https://blog.csdn.net/qq_38211541/article/details/117306580
作者:前端黄柠檬
链接:http://www.qianduanheidong.com/blog/article/115977/8fd675c4d53e1d68f3df/
来源:前端黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 前端黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-3
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!