题目:
1.合并两个有序链表
2.相交链表 (快慢指针) 有点难度,不好想(我是菜鸡)
3.删除链表中的节点
4.从尾到头打印链表
5.环形链表Ⅱ (快慢指针) 有点难度,不好想
6. 链表中倒数第K个节点 (快慢指针) 有点难度,不好想
7.反转链表
答案
//1.合并两个有序链表 (指针法)
var mergeTwoLists = function(list1, list2) {
let head = new ListNode(0);
let pre = head;//head和pre都指向一个新链表的head节点
while(list1 && list2){ //只要有一个链表为空就结束
if(list1.val > list2.val){
pre.next = list2;
list2 = list2.next; //更新链表2(变短)
} else{
pre.next = list1;
list1 = list1.next;
}
pre = pre.next;
}
pre.next = list1 ? list1 : list2; //将目前不为空的链表缀在后边
return head.next;
};
//2.相交链表
var getIntersectionNode = function(headA, headB) {
if(headA === null || headB === null) return null;
let a = headA, b = headB;
while(a !== b){
a = a !== null ? a.next : headB; //a走到null的地方从headB开始
b = b !== null ? b.next : headA; //不能写b = b.next !== null ? b.next : headA;
}
return a;
};
//3.删除链表中的节点
var deleteNode = function(node) {
node.val = node.next.val;
node.next = node.next.next;
};
//4.从尾到头打印链表
var reversePrint = function(head) {
let res = [];
while(head){
res.unshift(head.val);
head = head.next;
}
return res;
};
//5.环形链表
//本题使用了快慢指针的思想。
//使用快指针进行迭代,如果快指针的下一个节点为 null,则返回 null,否则快指针走两步,慢指针走一步。
//当快慢指针相遇后就说明有环,于是将快指针重置到头节点,然后快慢指针再每次走一步,当它们再次相遇后就是环的入口。
var detectCycle = function(head) {
let fast = head, slow = head;
while(fast){
if(fast.next === null) return null;
fast = fast.next.next;
slow = slow.next;
if(fast === slow){
fast = head;
while(true){
if(fast === slow) return slow;
fast = fast.next;
slow = slow.next;
}
}
}
return null;
};
//6.链表中倒数第K个节点
//先让快指针走 k 步,走完 k 步之后,快慢指针一起走,返回慢指针。
var getKthFromEnd = function(head, k) {
let fast = head, slow = head;
while(fast){
fast = fast.next;
k--;
if(k < 0){
slow = slow.next;
}
}
return slow;
};
// 7.反转链表
//解构赋值
var reverseList = function(head) {
let prev = null;
while(head){
//不能写成下面这样
// head.next = prev;
// prev = head;
// head = head.next; //head.next已经变为null了
[head.next, prev, head] = [prev, head, head.next] //可以理解为解构赋值右边在当次循环中已经一次性准备好了prev, head, head.next,而不是上边的一行一行的会有变动
}
return prev;
};
//8.删除链表的倒数第 N 个结点
var removeNthFromEnd = function(head, n) {
let fast = slow = head;
while(n){
n--;
fast = fast.next;
}
// 如果 n 和 链表中总结点个数相同,即要删除的是链表头结点时,fast 经过上一步已经到外面了
if(!fast){
return head.next;
}
while(fast.next){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return head;
};