程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2023-06(3)

【JavaScript 算法】-- 链表问题整理和解决思路总结

发布于2021-05-30 12:29     阅读(1493)     评论(0)     点赞(11)     收藏(3)


一、链表

链表和数组相似,它们都是有序的列表、都是线性结构(有且仅有一个前驱、有且仅有一个后继)。不同点在于,链表中,数据单位的名称叫做“结点”,而结点和结点的分布,在内存中可以是离散的。

在链表中,每一个结点的结构都包括了两部分的内容:数据域和指针域。JS 中的链表,是以嵌套的对象的形式来实现的:

  1. {
  2. // 数据域
  3. val: 1,
  4. // 指针域,指向下一个结点
  5. next: {
  6. val:2,
  7. next: ...
  8. }
  9. }

大概是这个样子:

二、链表结点的创建

创建链表结点,咱们需要一个构造函数,大概是这种形式:

  1. function ListNode(val) {
  2. this.val = val;
  3. this.next = null;
  4. }
  5. const node = new ListNode(1)
  6. node.next = new ListNode(2)

三、链表的考点

记住在处理链表问题时:处理链表的本质,是处理链表结点之间的指针关系,也就是next指针

链表的考点一般分为以下三类:

  • 链表的处理:合并删除等(删除是重点中的重点!)
  • 链表的反转及其衍生题目
  • 链表成环问题及其衍生题目

1、合并或删除问题

合成问题:

真题描述:将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有结点组成的。 (leetcode  21)

  1. /**
  2. * Definition for singly-linked list.
  3. * function ListNode(val, next) {
  4. * this.val = (val===undefined ? 0 : val)
  5. * this.next = (next===undefined ? null : next)
  6. * }
  7. */
  8. /**
  9. * @param {ListNode} l1
  10. * @param {ListNode} l2
  11. * @return {ListNode}
  12. */
  13. var mergeTwoLists = function (l1, l2) {
  14. let node = new ListNode();
  15. let cur = node;
  16. while (l1 && l2) {
  17. if(l1.val <= l2.val){
  18. cur.next = l1;
  19. l1 = l1.next
  20. } else {
  21. cur.next = l2;
  22. l2 = l2.next;
  23. }
  24. cur = cur.next
  25. }
  26. cur.next = l1 !== null ? l1:l2;
  27. // 返回node.text 很关键
  28. return node.next
  29. };

删除问题:

真题描述:给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。(leetcode 83)

  1. /**
  2. * Definition for singly-linked list.
  3. * function ListNode(val, next) {
  4. * this.val = (val===undefined ? 0 : val)
  5. * this.next = (next===undefined ? null : next)
  6. * }
  7. */
  8. /**
  9. * @param {ListNode} head
  10. * @return {ListNode}
  11. */
  12. // 输入:head = [1,1,2]
  13. // 输出:[1,2]
  14. var deleteDuplicates = function (head) {
  15. let cur = head
  16. while (cur && cur.next) {
  17. if (cur.val === cur.next.val) {
  18. cur.next = cur.next.next
  19. } else {
  20. cur = cur.next
  21. }
  22. }
  23. return cur.next
  24. };

真题描述:给定一个排序链表,删除所有含有重复数字的结点,只保留原始链表中 没有重复出现的数字。(leetcode 82)

  1. /**
  2. * Definition for singly-linked list.
  3. * function ListNode(val, next) {
  4. * this.val = (val===undefined ? 0 : val)
  5. * this.next = (next===undefined ? null : next)
  6. * }
  7. */
  8. /**
  9. * @param {ListNode} head
  10. * @return {ListNode}
  11. */
  12. const deleteDuplicates = function(head) {
  13. // 极端情况:0个或1个结点,则不会重复,直接返回
  14. if(!head || !head.next) {
  15. return head
  16. }
  17. let dummy = new ListNode()
  18. dummy.next = head
  19. let cur = dummy
  20. while(cur.next && cur.next.next) {
  21. if(cur.next.val === cur.next.next.val) {
  22. let val = cur.next.val
  23. while(cur.next && cur.next.val===val) {
  24. cur.next = cur.next.next
  25. }
  26. } else {
  27. cur = cur.next
  28. }
  29. }
  30. // 返回链表的起始结点
  31. return dummy.next;
  32. };

2、链表反转问题

一般情况下这类问题的关键时通过双指针法来解决(答案稍微有点复杂,我就不写自己答案了)

提示:第一个问题是一个经典的使用快慢指针来解决的链表问题,可以通过这个问题学习双指针。接下来再来带着双指针的思路来解决反转问题

真题描述:给定一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。(leetcode 22)

真题描述:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。(完全反转  leetcode  203)

真题描述:反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。(局部反转 leetcode 92)

3、链表成环问题

真题描述:给定一个链表,判断链表中是否有环。(判断是否成环  leetcode 141)

提示:解决这类问题的核心是设 标识(flag),两道题的思路都是一样的

  1. /**
  2. * Definition for singly-linked list.
  3. * function ListNode(val) {
  4. * this.val = val;
  5. * this.next = null;
  6. * }
  7. */
  8. /**
  9. * @param {ListNode} head
  10. * @return {boolean}
  11. */
  12. var hasCycle = function (head) {
  13. while (head) {
  14. if (head.flag) {
  15. return true
  16. } else {
  17. head.flag = true;
  18. head = head.next
  19. }
  20. }
  21. return false
  22. };

真题描述:给定一个链表,返回链表开始入环的第一个结点。 如果链表无环,则返回 null。(定位环启动 leetcode 142)

四、解决思路总结 !!!

  1. 链表问题(一般都是使用 while循环遍历
  2. 如果题目输入是整个链表时,对于这种问题。它的链路循环,一般是通过创建一个新的指向头部的节点(dummy节点),以它为头开始循环。dummy节点可以帮我们处理掉头结点为空的边界问题,帮助我们简化解题过程
  3. 对于链表反转问题 -- 通过双指针或者三指针的方式
  4. 对于链表成环问题 -- 通过设立标识(flag)的方式来解决

带着这个思路解决链表问题,一般的题目应该都能解决

 

原文链接:https://blog.csdn.net/qq_38211541/article/details/117306580




所属网站分类: 技术文章 > 博客

作者:前端黄柠檬

链接:http://www.qianduanheidong.com/blog/article/115977/8fd675c4d53e1d68f3df/

来源:前端黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

11 0
收藏该文
已收藏

评论内容:(最多支持255个字符)