文章目录
41 排序链表 42 合并k个升序链表 43 LRU缓存 44 二叉树的中序遍历 45 二叉树的最大深度
41 排序链表
递归 + 归并排序 找到链表中心点,从中心点将链表一分为二。奇数个节点找中心点,偶数个节点找中心左边的点作为中心点。 快慢指针找中心点,当快指针移动到该段链表的最后一个元素时,慢指针所指向的节点为中心点。 找到中心点后,中心点.next = null,将链表从中间断开。分别将前一半链表的头节点(head)和后一半链表的头节点(中心点.next)进行下一次划分。 注意:快慢指针初始化时,快指针比慢指针快一步,方便链表只有2个节点时划分链表。 合并有序链表: (1) 建立新节点作为新链表的哨兵节点。 (2) left,right 分别指向两个链表的头部,比较两个指针处节点值的大小,从小到大插入到有序链表中,指针交替前进,直至其中一个链表为空。将剩余的链表直接插入到有序链表的尾部。 (3) 返回哨兵节点.next。
var sortList = function ( head ) {
if ( head == null || head. next == null ) {
return head;
}
let slow = head, fast = head. next;
while ( fast != null && fast. next != null ) {
slow = slow. next;
fast = fast. next. next;
}
let tmp = slow. next;
slow. next = null ;
let left = sortList ( head) ;
let right = sortList ( tmp) ;
let dummy = new ListNode ( ) ;
let res = dummy;
while ( left != null && right != null ) {
if ( left. val < right. val) {
dummy. next = left;
left = left. next;
} else {
dummy. next = right;
right = right. next;
}
dummy = dummy. next;
}
dummy. next = left? left: right;
return res. next;
} ;
42 合并k个升序链表
方法1:最小堆。将头节点放入堆中,弹出最小值node,此时将node.next放入堆中,一直取到堆为空为止,每次取出最小值时,都将最小值的下一个节点放入堆中。 方法2:分治。这里给出该方法的代码。 将链表数组lists一分为二,先合并前一半链表,再合并后一半链表,最后完成全部链表的合并。 中心点为mid,前一半链表的区域为[左,mid],后一半链表的区域为[mid + 1,右]。
var merge = function ( left, right ) {
let dummy = new ListNode ( ) ;
let cur = dummy;
while ( left != null && right != null ) {
if ( left. val < right. val) {
cur. next = left;
left = left. next;
} else {
cur. next = right;
right = right. next;
}
cur = cur. next;
}
cur. next = left? left: right;
return dummy. next;
}
var mergeKLists = function ( lists ) {
function partition ( i, j ) {
if ( i == j) {
return lists[ i] ;
}
if ( i > j) {
return null ;
}
let mid = Math. floor ( ( i + j) / 2 ) ;
let left = partition ( i, mid) ;
let right = partition ( mid + 1 , j) ;
return merge ( left, right) ;
}
return partition ( 0 , lists. length - 1 )
} ;
43 LRU缓存
哈希表 + 双向链表 put: ① key不存在:创建新节点,添加进哈希表,添加到链表头部。如果当前容量 > capacity,删除链表尾部节点,删除哈希表中对应的项。 ② key存在:通过哈希表找到key所在的节点,改变value,移动到链表头部。 get: ① key不存在:返回 -1。 ② key存在:通过哈希表找到key所在的节点,移动到链表头部,返回value。 这里给出的代码直接使用哈希表实现各类操作。 this.map.delete(key); this.map.set(key, value);
:先删除,再将该节点添加到最后。this.map.keys().next().value;
:哈希表中第一个键值。
var LRUCache = function ( capacity ) {
this . capacity = capacity;
this . map = new Map ( ) ;
} ;
LRUCache . prototype. get = function ( key ) {
if ( this . map. has ( key) ) {
let value = this . map. get ( key) ;
this . map. delete ( key) ;
this . map. set ( key, value) ;
return value;
} else {
return - 1 ;
}
} ;
LRUCache . prototype. put = function ( key, value ) {
if ( this . map. has ( key) ) {
let value = this . map. get ( key) ;
this . map. delete ( key) ;
}
this . map. set ( key, value) ;
if ( this . map. size > this . capacity) {
this . map. delete ( this . map. keys ( ) . next ( ) . value) ;
}
} ;
44 二叉树的中序遍历
var inorderTraversal = function ( root ) {
var res = [ ] ;
var traversal = function ( root ) {
if ( root == null ) {
return ;
}
traversal ( root. left) ;
res. push ( root. val) ;
traversal ( root. right) ;
}
traversal ( root) ;
return res;
} ;
var inorderTraversal = function ( root ) {
var res = [ ] ;
var vis = [ ] ;
while ( root != null || vis. length != 0 ) {
if ( root != null ) {
vis. push ( root) ;
root = root. left;
} else {
root = vis. pop ( ) ;
res. push ( root. val) ;
root = root. right;
}
}
return res;
} ;
45 二叉树的最大深度
深度:任意节点到根节点的距离,使用前序遍历。 高度:任意节点到叶子节点的距离,使用后序遍历。 根节点的高度就是二叉树的最大深度。 这里使用后序遍历,即通过求根节点高度得出二叉树的最大深度。
var maxDepth = function ( root ) {
if ( root == null ) {
return 0 ;
}
var leftheight = maxDepth ( root. left) ;
var rightheight = maxDepth ( root. right) ;
var height = Math. max ( leftheight, rightheight) + 1 ;
return height;
} ;