构造链表
通过倒叙 arr[len-1]然后不断 curNode进行赋值next是当前curNode(倒推思想)
class Node {
constructor(value) {
this.val = value
this.next = undefined
}
}
class NodeList {
constructor(arr) {
if (arr.length) {
const len = arr.length
let curNode = {
value: arr[len - 1]
}
for (let i = len - 2; i >= 0; i--) {
curNode = {
value: arr[i],
next: curNode
}
}
return curNode
}
}
}
链表排序
- swap交互位置
- sort函数双指针思想-找出目标位置-不断进行左右互换
- 递归终止标志 if (begin !== end) 进行结束
- 内部partion函数进行内部 while循环 大小比较 swap交换位置 返回p
var swap = (p, q) => {
let val = p.val
p.val = q.val
q.val = val
}
var partion = (begin, end) => {
let val = begin.val
let p = begin
let q = begin.next
while (q !== end) {
if (q.val < val) {
swap(p.next, q)
p = p.next
}
q = q.next
}
swap(p, begin)
return p
}
var sort = (begin, end) => {
if (begin !== end) {
let part = partion(begin, end)
sort(begin, part)
sort(part.next, end)
}
}
var head = new NodeList([4, 1, 3, 2, 7, 9, 9, 10, 12, 6])
sort(head)
var res = []
var next = head
while (next) {
res.push(next.val)
next = next.next
}
核心代码解析
- 首先有一个基准值进行大小比较-一般是第一个值 begin.val
- p慢指针-一般从第一个开始-用户和快指针交换-作为最后的基准点返回
- q块指针一般从第二个开始-和一开始的基准值val进行比较
- q指针小就和p指针交换那个值的位置
- 交换之后我们就可以保证在p指针左边都是小于一开始的基准值 val的
var partion = (begin, end) => {
let val = begin.val
let p = begin
let q = begin.next
while (q !== end) {
if (q.val < val) {
swap(p.next, q)
p = p.next
}
q = q.next
}
swap(p, begin)
return p
}
环形链表
var isCircle = (head) => {
let slow = head
let fast = head.next
while(1) {
if(!fast||!fast.next) {
return false
} else if (fast===slow || fast.next === slow) {
return true
} else {
slow = slow.next
fast = fast.next.next
}
}
}
var head = new NodeList([6,1,2,5,7,9])
head.next.next.next.next.next.next = head.next
isCircle(head)
核心思想解析
- fast指针走的快 slow指针走的慢
- fast指针先进入这个位置 碰上或者说fast在slow后面说明有环
- fast走完都没有相等的时候说明没环
开挂
var isCircle = (head) => {
try {
JSON.stringify(head)
return false
} catch(e) {
return true
}
}
js反转链表
//
function reverseLink (link) {
let prevNode = undefined
let curNode = undefined
let nextNode = link
while (nextNode) {
if (curNode && !prevNode) {
delete curNode.next
}
if (curNode && prevNode) {
curNode.next = prevNode
}
prevNode = curNode
curNode = nextNode
nextNode = nextNode?.next
}
curNode.next = prevNode
return curNode
}
核心解析
- 每次把当前指针指向前一个指针完成链表反转
- 定义三个指针 前指针 先指针 后指针
- 首先每一次这三个指针都会按顺序进行替换前进一个指针
临界值处理
- 遍历到最后nextNode为undefined的时候
- 当前指针 curNode到最后一个位置还没有反指prevNode
- 如果!prevNode为false 说明curNode才来到第一个
- 这部分的之前指向的prevNode是undefined-应当删除避免死循环
- 解析来有值的时候就进行正常的反指curNode.next = prevNode
删除链表中的重复节点
function deleteNode(pHead) {
if (pHead == null || pHead.next == null) return pHead;
const head = { next: pHead };
let pre = head;
let last = head.next;
while (last) {
if (last.next && last.val === last.next.val) {
while (last.next && last.val === last.next.val) {
last = last.next;
}
pre.next = last.next;
last = last.next;
} else {
pre = pre.next;
last = last.next;
}
}
return head.next;
}
核心解析
- 删除链表节点-就是让这个节点失去引用被垃圾回收
- 指向不重复的那个节点-那么前面的那个重复节点就会被垃圾回收
- 创建pre和last指针
- last指针不断往后后进行比较last.val和last.next.val进行比较是否相等-
- 如果相等是重复节点-一直循环找不到不重复节点
- prev每次都指向不重复的节点last
临界值
- last&&last.next
- 最后return的时候注意reutrn head.next才是我们要返回的节点