单链表是什么
已经熟悉单链表概念的读者可以跳至单链表的实现或习题。
链表和数组很像,它们都是线性的存储结构,它们的不同点是数组是用一段连续的内存地址来存储数据,这也是为什么数组可以通过下标来直接访问的原因。
链表是相对松散的线性结构,也就是说链表中每个节点的物理地址可能不是连续的。
数组读取数据的时间复杂度是O(1),而链表则是O(n),因为要访问链表的某个节点必须从头开始遍历。
链表中的一个节点可以分为两部分:指针域和数据域。
指针域是用来指向下一个节点的位置,而数据域则是用来存储这个节点表示的数据。
链表常用场景
- 操作系统内的动态内存分配 (一种实现方式)
- LRU 缓存淘汰算法
- …
单链表的实现
单链表的实现方式主要有两种,通过对象引用的方式和数组方式
1.对象形式
class ListNode {
val: any
next: ListNode | null
constructor(val: any, next: ListNode) {
this.val = val === undefined ? 0 : val
this.next = next === undefined ? null : next
}
}
function checkChain(head: ListNode) {
let result = ''
while (head) {
result += head.val + '->'
head = head.next
}
console.log(result)
}
// main
const head = new ListNode(0, null)
const node1 = new ListNode(1, null)
const node2 = new ListNode(2, null)
const node3 = new ListNode(3, null)
head.next = node1
node1.next = node2
node2.next = node3
checkChain(head) // 0->1->2->3->
2.数组形式
// @ts-ignore
const data: number[] = new Array(10).fill(0)
// @ts-ignore
const next: number[] = new Array(10).fill(0)
const add = (lastPointer: number, curPointer: number, val: number) => {
next[lastPointer] = curPointer
data[curPointer] = val
}
// main
//* 定义头节点
const head = 3
data[3] = 0
//* 添加后续节点
add(3, 5, 1)
add(5, 2, 2)
add(2, 7, 3)
add(7, 9, 100)
//* 遍历链表
let p = head
let result = ''
while (p !== 0) {
result += `${
data[p]}->`
p = next[p]
}
console.log(result) // 0->1->2->3->100->
习题
以下是在LeetCode上有关单链表的习题,有条件的读者可以边看边做。
只要是不看答案就写不出来的都不算是掌握了。
===================================
leetCode 141 环形链表
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
解题思路:
使用快慢指针,慢指针每次走一步,快指针每次走两步,如果有环,两个指针迟早会指向同一个节点。
由于每次快指针都比慢指针多走一步,所以当两指针都进入环时,每走一次二者的距离都少1。
function hasCycle(head: ListNode | null): boolean {
if (!head || !head.next) return false
let slow = head, fast = head
do {
slow = slow.next
fast = fast.next.next
} while (slow !== fast && fast && fast.next)
return !!fast && !!fast.next
};
===================================
leetCode 142 环形链表2
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表