关于链表,所有赋值都是直接对其指针操作。我的偷懒心得,就是通过把他放到数组里面,通过下标实现各向遍历,但是要注意指针不要乱指
19删除链表的倒数第N个节点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
var removeNthFromEnd = function(head, n) {
let tmp = head;
let cache = []; // 存储每个节点的指针信息
let index = 0;
while(tmp) {//把链表放进数组里面
cache[index] = tmp;
index ++;
tmp = tmp.next;
}
// 存在则删除节点
if (cache[index - n - 1]) {
cache[index - n - 1].next = cache[index - n - 1].next.next;
} else {
// 不存在则删除头节点
if (head.next) {
head.val = head.next.val;
head.next = head.next.next;
} else {
head = head.next;
}
}
return head;
};
21 合并两个有序链表
递归
var mergeTwoLists = (l1, l2)=> {
if(l1===null){
return l2;
}else if(l2==null){
return l1;
}else if(l1.val<l2.val){
l1.next=mergeTwoLists(l1.next,l2);
return l1;
}else{
l2.next=mergeTwoLists(l1,l2.next);
return l2;
}
};
23合并K个有序链表
思路一:依次合并两个有序链表,即调用21中的mergeTwoLists()
/**
* @param {ListNode[]} lists
* @return {ListNode}
*/
var mergeTwoLists = (l1, l2)=> {
if(l1===null){
return l2;
}else if(l2==null){
return l1;
}else if(l1.val<l2.val){
l1.next=mergeTwoLists(l1.next,l2);
return l1;
}else{
l2.next=mergeTwoLists(l1,l2.next);
return l2;
}
};
var mergeKLists = function(lists) {
let result=null;
for(let i=0;i<lists.length;i++){
result=mergeTwoLists(result,lists[i]);
}
return result;
}
思考维护一个小顶堆
24 两两交换链表的顺序
一次变序后AaBb变为aABb,如果是返回head指针,他指向的是A,接下来链表中只有ABb
利用递归和数组解构的语法
数组解构可以实现两组赋值
递归可以简化跳出循环的条件,即不再调用下一次递归有自己的返回值时
var swapPairs = function(head) {
if (!head || !head.next) return head;//0或者1
let [fst, snd] = [head, head.next];
[fst.next, snd.next] = [swapPairs(snd.next), fst];
/* 等同于
fst.next=swapPairs(snd.next);
snd.next=fst;*/
return snd;
};
25 K个一组反转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
进阶:
你可以设计一个只使用常数额外空间的算法来解决此问题吗?
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
把链表放进数组里面,用数组下标索引实现逆序,再加上递归
var reverseKGroup = function(head, k) {
let cache = []; // 存储每个节点的指针信息
let i=-1,temp=head;
while(++i<k&&temp) {//把链表放进数组里面
cache[i]=temp;
temp = temp.next;
}
if(i--<k) return head;//小于k不用逆序,全遍历之后i=k
while(cache[i]&&i>0){
cache[i].next=cache[--i];
}
cache[0].next=reverseKGroup(temp,k);
return cache[k-1];
};
61 旋转链表
固定好头尾指针后,将链表连成环,然后将头尾指针一起向后移(长度-k%长度)次
var rotateRight = function(head, k) {
if(!head||k==0) return head;
let i=1,tail=head;
while(tail.next){//找到尾巴
tail=tail.next;
i++;//长度
}
tail.next=head;//连成环
let count=i-k%i;//只能顺序移所以需要移长度-k次
while(count--){
tail=tail.next;
head=head.next;
}
tail.next=null;//断开循环
return head;
};
82删除链表中重复元素
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字
var deleteDuplicates = function(head) {
let cur = new ListNode();
cur.next = head;
head = cur;
while (cur.next && cur.next.next) {//重复的节点一个都不留,所以比较下一位和下下一位
if (cur.next.val === cur.next.next.val) {
const val = cur.next.val;
while (cur.next && val === cur.next.val) {
cur.next = cur.next.next;
}
} else {
cur = cur.next;
}
}
return head.next;
};