链表
初始链表结构
class Node {
constructor(value) {
this.value = value
this.next = null
}
}
let head = new Node(1)
数组实现
let data = new Array(10)
let next = new Array(10)
function add(index, nextIndex, val) {
next[index] = nextIndex
data[nextIndex] = val
}
add(3, 5, 1)
add(5, 9, 2)
add(9, 0, 10)
链表结构为 3 --> 5 --> 9
值 1 2 10
应用场景图
1、操作系统内的动态内存分配 --- 链表
2、LRU缓存淘汰算法
leetcode实战解题
题 141、 环形链表(链表判环)
给定一个链表,判断链表中是否有环。
解题思路: 一个快走(走两步)一个慢走(走一步) 若相遇则有环,为null则无环
var hasCycle = function (head) {
let p = head
if (!p) {
return false
}
let q = p.next
if (!q) {
return false
}
while (p && q) {
if (p === q) {
break
}
p = p.next
q = q.next && q.next.next
}
return (p === q) && p !== null
};
题 142、 环形链表(找到入环的第一个节点)
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
解题思路: 一个快走(走两步)一个慢走(走一步),找到相遇节点。 然后有一个节点从头开始走,另一个节点从相遇点走到再次相遇点,则是入环节点。
var detectCycle = function (head) {
if (!head) {
return head
}
let hasCycle = false
let p = head, q = head
while (q.next && q.next.next) {
p = p.next
q = q.next.next
if (p === q) {
hasCycle = true
break
}
}
let newp = head
if (hasCycle) {
while (newp != q) {
newp = newp.next
q = q.next
}
return newp
} else {
return null
}
};
题 202、 快乐数
解题思路: 一个快走(走两步,求2步快乐数)一个慢走(求1步快乐数),若相遇则无限。
题 206、 反转链表
解题思路: 1.定义新节点初始为null, 做循环不断将链表的节点指向新链表
2.递归
var reverseList = function (head) {
if (!head || !head.next) {
return head
}
let tail = head.next
let p = reverseList(head.next)
head.next = tail.next
tail.next = head
return p
};
题 92、 反转链表(区间反转)
var reverseBetween = function (head, left, right) {
if (!head || !head.next) {
return head
}
if (left > right) {
return head
}
let nh = new ListNode()
nh.next = head
let h = nh
let ctn = right - left + 1
while (--left) {
h = h.next
}
let p = reverseN(h.next, ctn)
h.next = p
return nh.next
};
// 区间反转
var reverseN = function (head, n) {
if (n === 1) {
return head
}
let tail = head.next
let p = reverseN(head.next, n - 1)
head.next = tail.next
tail.next = head
return p
}
题 25、 k个一组反转链表(区间反转)
var reverseN = function (head, n) {
if (n === 1) {
return head
}
let tail = head.next
let p = reverseN(head.next, n - 1)
head.next = tail.next
tail.next = head
return p
}
题 61、 旋转链表
记录尾节点,走k位,然后断开
题 91、 删除链表倒数第n个节点
先建个虚拟节点p,p走n步得到q,做循环当pq一起走,q为空的时候停下来。此时处理p
题 83、删除链表中的重复节点
判断下一个是否相等,持续性删除后面节点,不等的话,p向后走一步
题 82、出现过重复的值都删掉
先建虚拟头节点, 比较下个节点和下下个节点,相等去找到不同的节点,然后链接
var deleteDuplicates = function (head) {
if (!head) {
return head
}
let ret = new ListNode()
ret.next = head
let p = ret
let q = head.next
while (p.next) {
if (hasRepet(p.next)) {
p.next = getNext(p.next)
} else {
p = p.next
}
}
return ret.next
};
function hasRepet(head) {
if (!head) {
return false
}
if (head.next && head.next.val === head.val) {
return true
}
return false
}
function getNext(p) {
if (!p) {
return p
}
let q = p.next
while (q && q.val === p.val) {
q = q.next
}
return q
}