203. 移除链表元素
使用虚拟头结点,虚拟头结点是为了解决链表在头结点操作时和在其他节点操作时操作不同而用的
function removeElements(head: ListNode | null, val: number): ListNode | null {
let newHead = null
let cur: ListNode = {
val: 0,
next: head
}
while (cur) {
if (cur.next && cur.next.val === val) {
cur.next = cur.next.next
} else {
cur = cur.next
if (!newHead) {
newHead = cur
}
}
}
return newHead
};
707. 设计链表
双向链表,需要注意的是改动时当前节点的prev和next、prev节点的next、next节点的prev都需要改动
class LinkedNode {
val: number
prev: LinkedNode | null
next: LinkedNode | null
}
class MyLinkedList {
vHead: LinkedNode
len: number = 0
constructor() {
this.vHead = { val: 0, prev: null, next: null }
}
print() {
let cur = this.first()
let s = ''
while (cur) {
s += (cur.val + '->')
cur = cur.next
}
console.log(this.len + ',' + s)
}
first(): LinkedNode | null {
return this.vHead.next
}
last(): LinkedNode | null {
let last = this.first()
while (last && last.next) {
last = last.next
}
return last
}
getNode(index: number): LinkedNode | null {
let cur = this.vHead
for (let i = 0; i <= index; i++) {
if (!cur) {
break
}
cur = cur.next
}
return cur
}
get(index: number): number {
const node = this.getNode(index)
return node ? node.val : -1
}
addAtHead(val: number): void {
const oldNode = this.vHead.next
const newNode = { val, prev: this.vHead, next: oldNode }
this.vHead.next = newNode
if (oldNode) {
oldNode.prev = newNode
}
this.len += 1
}
addAtTail(val: number): void {
const last = this.last()
if (last) {
last.next = { val, prev: last, next: null }
this.len += 1
} else {
this.addAtHead(val)
}
}
addAtIndex(index: number, val: number): void {
const node = this.getNode(index)
if (index === this.len) {
this.addAtTail(val)
} else if (node && index < this.len) {
const newNode = { val, prev: node.prev, next: node }
if (node.prev) {
node.prev.next = newNode
node.prev = newNode
}
this.len += 1
}
}
deleteAtIndex(index: number): void {
const node = this.getNode(index)
if (node) {
if (node.prev) {
node.prev.next = node.next
}
if (node.next) {
node.next.prev = node.prev
}
this.len -= 1
}
}
}
206. 反转链表
双指针法:pre和cur两个指针同时移动,每移动一次就反转一次指向,最后pre移到尾结点也即新链表的头结点,注意每次tmp的保存
function reverseList(head: ListNode | null): ListNode | null {
let cur = head
let pre = null
let tmp = null
while (cur) {
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
}
return pre
};
递归法:每次递归里反转两个节点
function reverseList(head: ListNode | null): ListNode | null {
return reverse(null, head)
};
function reverse(pre: ListNode | null, cur: ListNode | null) {
if (!cur) {
return pre
}
const tmp = cur.next
cur.next = pre
return reverse(cur, tmp)
}