javascript刷题顺序按照[Leetcode分类顺序表](挂了。。现在就哪里不会刷哪里)(cspiration.com/leetcodeCla…) 👑->VIP题目
链表
面试题 02.03. 删除中间节点
这题要注意的是和传统的链表删除节点有丢丢不一样,因为传入的node是要删除的节点到结尾的这段链表,当前node的pre节点未知,所以这里是先把后一个节点的val赋值到当前节点上,然后再用传统方法删掉当前节点的next节点
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} node
* @return {void} Do not return anything, modify node in-place instead.
*/
var deleteNode = function(node) {
node.val = node.next.val;
node.next = node.next.next;
};
剑指 Offer II 023. 两个链表的第一个重合节点
定义两个指针分别指向A和B,然后遍历链表,当遍历完当前链表后,两个指针交换链表继续遍历,如果两个指针指向同一个节点,则返回这个节点(即第一个重合节点)
这里要注意的地方是无论有没有重合点,两边指针走过(m+n)后就停止。
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
var getIntersectionNode = function(headA, headB) {
let p = headA;
let q = headB;
while(p || q){
if (p===null) {
p = headB;
}
if (q===null) {
q = headA;
}
if (p === q) {
return p
} else {
p = p.next;
q = q.next;
}
}
return null
};
剑指 Offer 06. 从尾到头打印链表
因为直接打印数组,用unshift可能更简洁(虽然核心思想是利用栈的FILO特性
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {number[]}
*/
var reversePrint = function(head) {
let arr = []
let curr = head
while(curr){
arr.unshift(curr.val)
curr = curr.next
}
return arr
};
剑指 Offer 24. 反转链表
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
let prev = null
let curr = head
while(curr){
const temp = curr.next;
curr.next = prev
prev = curr
curr = temp
}
return prev
};
剑指 Offer 35. 复杂链表的复制
- 方法一:用空间换时间,时间复杂度O(n) 空间复杂度O(n)
/** * // Definition for a Node. * function Node(val, next, random) { * this.val = val; * this.next = next; * this.random = random; * }; */ /** * @param {Node} head * @return {Node} */ var copyRandomList = function(head) { if(!head) return head //如果是空链表则直接返回 let curr = head; const map = new Map(); // 先把链表全都存到map中 while(curr){ map.set(curr,new Node(curr.val)); curr = curr.next; } curr = head; while(curr){ // Map中get不存在的key,返回值是undefined map.get(curr).next = map.get(curr.next) === undefined ? null : map.get(curr.next); map.get(curr).random = map.get(curr.random); curr = curr.next; } return map.get(head) }; - 方法二:时间复杂度O(n) 空间复杂度O(1)
/** * // Definition for a Node. * function Node(val, next, random) { * this.val = val; * this.next = next; * this.random = random; * }; */ /** * @param {Node} head * @return {Node} */ var copyRandomList = function(head) { if(!head) return head; // 第一步根据原始链表的每个节点N创建对应的N',并把N'链接在N后面 let curr = head; while(curr){ curr.next = new Node(curr.val,curr.next); curr = curr.next.next; } // 第二步设置复制出来的节点的random。假设原始链表上N的random指向节点S,那么其对应复制出来的N'是N的next指向的节点,S'同样也是S的next指向的节点 curr = head; while(curr){ if(curr.random !== null){ curr.next.random = curr.random.next; } curr = curr.next.next; } // 第三步把这个长链表拆分成两个链表,最后返回复制链表的头节点 curr = head.next let dupl = curr; let prev = head; while(prev.next && curr.next){ prev.next = prev.next.next; curr.next = curr.next.next; prev = prev.next; curr = curr.next; } prev.next = null; // 返回新链表头节点 return dupl };