当前位置:网站首页>【js】-【链表-应用】-学习笔记
【js】-【链表-应用】-学习笔记
2022-06-24 19:42:00 【有趣的学习】
【js】-【链表-应用】-学习笔记
声明:本笔记是根据掘金小册总结的,如果要学习更多细节,请移步https://juejin.cn/book/6844733800300150797
1 链表的合并
描述:
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有结点组成的
输入:
1->2->4,
1->3->4
输出:
1->1->2->3->4->4
思路:
下图中红色箭头表明穿针的过程与方向
- 新建一个头节点,建立一个指针
cur,作为针- 把比较小的那个节点串起来,指针向前移,当前 cur指针也往前移
- 最后处理没有走完的链表,拼在最后
const mergeTwoLists = function(l1, l2) {
#1 定义头结点,确保链表可以被访问到
let head = new ListNode()
// cur 这里就是咱们那根“针”
let cur = head
// “针”开始在 l1 和 l2 间穿梭了
while(l1 && l2) {
# 2.1如果 l1 的结点值较小,先串起 l1 的结点,l1向前走
if(l1.val<=l2.val) {
cur.next = l1
l1 = l1.next
} else {
#2.2 如果l2 较小时,串起 l2 结点,l2 向前一步
cur.next = l2
l2 = l2.next
}
#3 “针”在串起一个结点后,也会往前一步
cur = cur.next
}
#4 处理链表不等长的情况
cur.next = l1!==null?l1:l2
// 返回起始结点
return head.next
};
2 链表结点的删除
1. 删除所有重复的元素
描述:
给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
输入:
1->1->2
输出:1->2
输入:
1->1->2->3->3
输出:1->2->3
const deleteDuplicates = function(head) {
#1 设定 cur 指针,初始位置为链表第一个结点
let cur = head;
#2 遍历链表
while(cur != null && cur.next != null) {
if(cur.val === cur.next.val) {
# 2.1 若当前结点和它后面一个结点值相等(重复),删除靠后的那个结点(去重)
cur.next = cur.next.next;
} else {
# 2.2 若不重复,继续遍历
cur = cur.next;
}
}
return head;
};
2 删除所有含有重复数字的结点
描述:
给定一个排序链表,删除所有含有重复数字的结点,只保留原始链表中 没有重复出现的数字
输入:
1->2->3->3->4->4->5
输出:1->2->5
输入:
1->1->1->2->3
输出:2->3
思路:
链表的第一个结点,因为没有前驱结点,导致我们面对它无从下手。这时我们就可以用一个dummy结点来解决这个问题。
1 定义dummy结点,指向头结点,cur从dummy遍历
2. 遇到一样的,记录val的值,开始循环遍历,把一样的都删除。不一样则跳过
3 返回dummy.next,即链表的起始节点
const deleteDuplicates = function(head) {
#1 极端情况:0个或1个结点,则不会重复,直接返回
if(!head || !head.next) {
return head
}
#2 dummy 登场,dummy 永远指向头结点
let dummy = new ListNode()
dummy.next = head
#3 cur 从 dummy 开始遍历
let cur = dummy
// 当 cur 的后面有至少两个结点时
while(cur.next && cur.next.next) {
// 对 cur 后面的两个结点进行比较
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;
};
dummy结点,模板代码
const dummy = new ListNode()
// 这里的 head 是链表原有的第一个结点
dummy.next = head
3 删除链表的倒数第 N 个结点(快慢指针)
描述:
给定一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
给定一个链表:
1->2->3->4->5, 和n = 2.
当删除了倒数第二个结点后,链表变为1->2->3->5.
思路:
- 定义dummy结点作为头结点的前驱, 快慢指针都从dummy开始
- 快指针先走n步,
- 快慢指针开始同步走,
- 删除慢指针的后继,即倒数第n个结点
- 返回dummy.next,即头结点
const removeNthFromEnd = function(head, n) {
#1 初始化 dummy 结点,指向头结点
const dummy = new ListNode()
dummy.next = head
#2 初始化快慢指针,均指向dummy
let fast = dummy
let slow = dummy
#3 快指针闷头走 n 步
while(n!==0){
fast = fast.next
n--
}
#4 快慢指针一起走
while(fast.next){
fast = fast.next
slow = slow.next
}
#5 慢指针删除自己的后继结点
slow.next = slow.next.next
// 返回头结点
return dummy.next
};
4.0 链表的反转(多指针)
描述:
定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点
输入:
1->2->3->4->5->NULL
输出:5->4->3->2->1->NULL
思路:
- 前驱结点
pre,当前结点cur,后继结点nextnext指向pre,然后pre和cur都继续后移- 最后返回
pre,就是新链表的头结点
const reverseList = function(head) {
#1 初始化前驱结点为 null
let pre = null;
#2 初始化目标结点为头结点
let cur = head;
#3 只要目标结点不为 null,遍历就得继续
while (cur !== null) {
// 记录一下 next 结点
let next = cur.next;
// 反转指针
cur.next = pre;
// pre 往前走一步
pre = cur;
// cur往前走一步
cur = next;
}
// 反转结束后,pre 就会变成新链表的头结点
return pre
};
4.1 局部反转一个链表
描述:
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
输入:
1->2->3->4->5->NULL, m = 2, n = 4
输出:1->4->3->2->5->NULL
思路
- 先定义
dummy,找到m的前驱,并保存下来lefthead- 从
m作为pre,cur指向pre.next开始翻转- 把
leftHead指向pre,start指向cur
// 入参是头结点、m、n
const reverseBetween = function(head, m, n) {
// 定义pre、cur,用leftHead来承接整个区间的前驱结点
let pre,cur,leftHead
#1 dummy结点
const dummy = new ListNode()
dummy.next = head
#2.0 p是一个游标,用于遍历,最初指向 dummy,往前走 m-1 步,走到整个区间的前驱结点处
let p = dummy
for(let i=0;i<m-1;i++){
p = p.next
}
#2.1 缓存这个前驱结点到 leftHead 里
leftHead = p
let start = leftHead.next // start 是反转区间的第一个结点
pre = start// pre 指向start
cur = pre.next // cur 指向 start 的下一个结点
#3 开始重复反转动作
for(let i=m;i<n;i++){
let next = cur.next// 记录一下 next 结点
cur.next = pre // 反转指针
pre = cur// pre 往前走一步
cur = next // cur往前走一步
}
#4 leftHead 的后继结点此时为反转后的区间的第一个结点
leftHead.next = pre
start.next=cur // 将区间内反转后的最后一个结点 next 指向 cur
return dummy.next // dummy.next 永远指向链表头结点
};
5 判断链表是否成环
- 改变结点,
flag
const detectCycle = function(head) {
while(head){
if(head.flag){
return head;
}else{
head.flag = true;
head = head.next;
}
}
return null;
};
2. 可以用map模拟 (个人喜欢,牢记)
const detectCycle = function(head) {
const visited = new Map();
while(head){
if(visited.has(head)){
return head;
}else{
visited.set(head)
head = head.next;
}
}
return null;
};
- 快慢指针
快指针走两步,慢指针走一步
如果相等了就有环
const detectCycle = function(head) {
if(!head) return null;
let slow=head,fast=head;
#1 快指针没到头就继续
while (fast !== null) {
#2 慢指针走一步,快指针走两步
slow = slow.next;
if (fast.next !== null) {
fast = fast.next.next;
} else {
return null;
}
#3 如果快慢指针相遇
if (fast === slow) {
let ptr = head;
while (ptr !== slow) {
ptr = ptr.next;
slow = slow.next;
}
return ptr;
}
}
return null;
};
我们再额外使用一个指针
ptr。
起始,它指向链表头部
;随后,它和slow每次向后移动一个位置。最终,它们会在入环点相遇。
边栏推荐
- 是否需要提高代码阅读能力?这有技巧
- Theoretical analysis of countermeasure training: adaptive step size fast countermeasure training
- China smallpox vaccine market trend report, technical innovation and market forecast
- laravel 添加helper文件
- Blogs personal blog test point (manual test)
- Vulnhub Vegeta: 1
- Gocolly manual
- Spark 离线开发框架设计与实现
- 01_SpingBoot 框架入门
- EPICS记录参考4--所有输入记录都有的字段和所有输出记录都有的字段
猜你喜欢

vulnhub Vegeta: 1

Vulnhub Vegeta: 1

vulnhub DC: 2

Epics record reference 2 -- epics process database concept
![[laravel series 7.9] test](/img/49/4b470a8b309bab4a83eed930dcce65.png)
[laravel series 7.9] test
15 lines of code using mathematical formulas in wangeditor V5

A big factory interview must ask: how to solve the problem of TCP reliable transmission? 8 pictures for you to learn in detail

03_SpingBoot 核心配置文件

Dig deep into MySQL - resolve the non clustered index of MyISAM storage engine

【ROS玩转Turtlesim小海龟】
随机推荐
【文本数据挖掘】中文命名实体识别:HMM模型+BiLSTM_CRF模型(Pytorch)【调研与实验分析】
F29oc analysis
High level application of SQL statements in MySQL database (I)
Docker installation MySQL simple without pit
docker-mysql8-主从
记录一下MySql update会锁定哪些范围的数据
docker安装mysql-简单无坑
[untitled]
China smallpox vaccine market trend report, technical innovation and market forecast
Non single file component
go Cobra命令行工具入门
laravel model 注意事项
Learn more about redis' eight data types and application scenario analysis
Paddledtx v1.0 has been released, and its security and flexibility have been comprehensively improved!
Construction equipment [4]
Selection (028) - what is the output of the following code?
Selection (027) - what is the output of the following code?
Financial management [5]
关于某手滑块的一些更新(6-18,js逆向)
China solar window market trend report, technical dynamic innovation and market forecast




