题型一:两两交换
题目:
给定⼀个链表,两两交换其中相邻的节点(不交叉),并返回交换后的链表。你不能只是单纯的改变节点内部的值,⽽是需要实际的进⾏节点交换。示例:原链表:1->2->3->4输出链表:2->1->4->3
要点:
- 保存好前一交换组的最后一个节点current,即交换前的第一个节点,用于拼接——current.next = 当前交换组的第二个节点
- 借助链表的头结点head来充当一开始的最后一个节点
function exchangeList(l) {
// 头节点
const head = new ListNode("#");
head.next = l;
let current = head; //指向前一交换组的最后一个节点
//循环条件用到了逻辑中断
while (current.next && current.next.next) {
let first = current.next;
let second = current.next.next;
// 交换,注意顺序问题
first.next = second.next;
second.next = first;
// 拼接
current.next = second;
// 更新current head不再改变了
current = first;
}
//跟着current指向第二个节点
return head.next;
}
题型二:K 个⼀组翻转链表
题目:
给你⼀个链表,每 k 个节点⼀组进⾏翻转,请你返回翻转后的链表。k 是⼀个正整数,它的值⼩于或等于链表的⻓度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。同样的,你不能只是单纯的改变节点内部的值,⽽是需要实际的进⾏节点交换。示例:给你这个链表: 1->2->3->4->5当 k = 2 时,应当返回 : 2->1->4->3->5当 k = 3 时,应当返回 : 3->2->1->4->5
要点一:如何翻转链表 ——prev + current ,注意翻转前用temp保存当前翻转节点的next
要点二:同题型一,需保存前一交换组的最后一个节点current,即交换前的第一个节点,用于拼接
要点三:判断是否还有k个元素 / 是否该翻转了——通过count计数变量取余k
示意图看不懂不要紧,简单过一下,有个印象,看完代码再回来看一遍,就会很清晰了
function reverseGroupOfList(l, k) {
// 头节点
const head = new ListNode("#");
head.next = l;
let start = head; //指向是前一组翻转后的最后一个节点
let end = l;
let count = 0;
while (end) {
count++;
if (count % k === 0) {
// 翻转时机
start = reverseList(start, end.next);
// 更新start end
end = start.next;
} else {
end = end.next;
}
}
return head.next;
}
翻转链表+返回前一组翻转后的最后一个节点 的函数:
// 翻转链表
// startNode是前一组翻转后的最后一个节点
// 返回翻转前的第一个节点
function reverseList(startNode, endNodeNext) {
let [prev, current] = [startNode, startNode.next];
//看本函数倒数第二行
const first = startNode.next;
// 不能直接endNode.next 指向变了
while (current !== endNodeNext) {
let temp = current.next; //保存翻转节点的下一节点
current.next = prev;
prev = current;
current = temp;
}
// 拼接
startNode.next = prev;
// 借助返回值保存下一组的第一个节点
// endNode.next指向变了
first.next = current;
return first;
}