-
Notifications
You must be signed in to change notification settings - Fork 645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
前端进阶算法4:链表原来如此简单(+leetcode刷题) #12
Comments
循环单链表的插入是有问题的,当链表为空时,插入会报错。最好在前面加一个length===0的判断 |
|
单链表中的删除节点remove是有问题的,没有考虑删除head节点 |
单链表中的insert 调用是不是少传了一个element? |
插入链表 可以使用哑节点,代码更清晰 this.insert = function(position, element) {
// 边界条件
if(position < 0 || position > length) {
return null
}
// 如果head不存在,直接赋值
if(!head) {
head = node
length ++
return
}
// 边界条件 END
let node = new Node(element)
// 新增一个哑节点
let dummy = new Node()
dummy.next = head
let curr = dummy
// 开始遍历寻找position位置之前的那个元素
for(let pos = 0; pos < position; pos ++) {
curr = curr.next
}
node.next = curr.next
curr.next = node
length ++
} |
拜谢作者,快要考数据结构导论了,发现了宝藏 |
代码很有问题 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
引言
链表相对于数组来说,要复杂的多,首先,链表不需要连续的内存空间,它是由一组零散的内存块透过指针连接而成,所以,每一个块中必须包含当前节点内容以及后继指针。最常见的链表类型有单链表、双链表以及循环链表。
学习链表最重要的是 多画图多练习 ,没有捷径可循,在遇到链表问题时,瓶子君总结了一下,可以按照以下五步骤:
本文会给常用链表(单链表、双链表以及循环链表)的基本操作已经代码实现,并给出实现思路,这些都是链表解题的基石,请务必掌握!⛽️⛽️⛽️
最后附赠一道 leetcode 题目,并按照链表解题五步骤给出答案!
下面开始本节的学习吧!!!👇👇👇
一、单链表
单链表结构:
1. 追加节点:
**确定解题的数据结构:**单链表
确定解题思路: 初始化一个节点(待追加节点),遍历到链尾,在尾节点后插入该节点
画图实现:
确定边界条件: 当链表为
null
,直接将head
指向待插入节点,不需要遍历代码实现:
解题完成✅
2. 查找:
**确定解题的数据结构:**单链表
确定解题思路: 遍历单链表,判断节点值是否等于待查找值,相等则返回
true
,否则继续遍历下一个节点,直到遍历完整个链表还未找到,则返回false
画图实现: 很简单,读者可以尝试画一下
确定边界条件: 当链表为
null
,可直接返回false
代码实现:
解题完成✅
3. 在 position 位置插入:
**确定解题的数据结构:**单链表
确定解题思路: 初始化一个节点(待插入节点
node
),遍历到position
前一个位置节点,在该节点后插入node
画图实现:
确定边界条件:
position
为0
时,直接将插入节点node.next
指向head
,head
指向node
即可,不需要遍历position < 0
或超出链表长度position > length
,都是有问题的,不可插入,此时直接返回null
,插入失败代码实现:
解题完成✅
4. 删除:
**确定解题的数据结构:**单链表
确定解题思路: 遍历单链表,找到待删除节点,删除
画图实现:
确定边界条件: 当链表为
null
,直接返回代码实现:
解题完成✅
5. 复杂度分析:
查找:从头节点开始查找,时间复杂度为 O(n)
插入或删除:在某一节点后插入或删除一个节点(后继节点)的时间复杂度为 O(1)
链表五步骤是不是很好用😊,下面看一下双链表👇
二、双链表
顾名思义,单链表只有一个方向,从头节点到尾节点,那么双链表就有两个方向,从尾节点到头节点:
1. 在 position 位置插入节点:
确定解题的数据结构: 双链表
确定解题思路: 初始化一个节点(待插入节点
node
),遍历链表到position
前一个位置节点,在该节点位置后插入node
画图实现:
确定边界条件:
当待插入位置
position < 0
或超出链表长度position > length
,都是有问题的,不可插入,此时直接返回null
,插入失败代码实现:
解题完成✅
2. 删除:
确定解题的数据结构: 双链表
确定解题思路: 遍历双链表,找到待删除节点,删除
画图实现:
确定边界条件: 当链表为
null
,直接返回代码实现:
解题完成✅
3. 查找:
双链表的查找和单链表类似,都是遍历链表,找到返回
true
,找不到返回false
。4. 复杂度分析:
查找:查找前驱节点或后继节点时间复杂度为 O(1),其它节点仍为 O(n)
插入或删除:插入或删除前驱节点或后继节点的时间复杂度都为 O(1)
三、循环单链表
循环单链表是一种特殊的单链表,它和单链表的唯一区别是:单链表的尾节点指向的是 NULL,而循环单链表的尾节点指向的是头节点,这就形成了一个首尾相连的环:
既然有循环单链表,当然也有循环双链表,循环双链表和双链表不同的是:
tail.next
(tail
的后继指针) 为null
,循环双链表的tail.next
为head
head.prev
(head
的前驱指针) 为null
,循环双链表的head.prev
为tail
这里以循环单列表为例
1. 在 positon 后插入:
确定解题的数据结构: 循环单链表
确定解题思路: 初始化一个节点(待插入节点
node
),遍历到position
前一个位置节点,在该节点后插入node
画图实现:
确定边界条件:
position
为0
时,需要遍历到尾节点,然后在尾节点后插入节点 , 并将head
指向position < 0
或超出链表长度position > length
,都是有问题的,不可插入,此时直接返回null
,插入失败代码实现:
解题完成✅
2. 查找:
和单链表类似,唯一不同的是:循环单链表的循环结束条件为
index++ < length
解题完成✅
3. 删除:
和单链表类似,唯一不同的是:循环单链表的循环结束条件为
index++ < length
解题完成✅
4. 复杂度分析
查找:循环链表从任一节点开始查找目标节点,时间复杂度为 O(n)
插入或删除:它和单链表一样,后继节点插入及删除的时间复杂度为 O(1)
四、leetcode21:合并两个有序链表
将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
欢迎将答案提交到 #11 , 让更多人看到,瓶子君也会在明日放上自己的解答。
五、认识更多的前端道友,一起进阶前端开发
前端算法集训营第一期免费开营啦🎉🎉🎉,免费哟!
在这里,你可以和志同道合的前端朋友们(200+)一起进阶前端算法,从0到1构建完整的数据结构与算法体系。
在这里,瓶子君不仅介绍算法,还将算法与前端各个领域进行结合,包括浏览器、HTTP、V8、React、Vue源码等。
在这里,你可以每天学习一道大厂算法题(阿里、腾讯、百度、字节等等)或 leetcode,瓶子君都会在第二天解答哟!
更多福利等你解锁🔓🔓🔓!
在公众号「前端瓶子君」内回复「算法」即可加入。你的关注就是对瓶子君最大的支持😄😄😄
The text was updated successfully, but these errors were encountered: