一、25 K个一组翻转链表
问题描述
给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
解题思路
1、递归
a、需要将链表按照k个一组进行分组,因此设置一个指针cur指向当前每一组的头节点。cur指针每次向前移动k步,直至链表结尾。对于每个分组,首先判断其长度是否大于等于k。若是,则翻转链表,反之则直接接入。
b、链表反转的思路可以参考206题(写在后面了,在这里不赘述)。
c、但是对于一个子链表除了翻转本身外还需要将当前子链表的头部和上一个子链表的尾部连接,以及将此时子链表的尾部与下一个子链表连接。因此,在翻转子链表的时候,我们不仅需要子链表头节点 head,还需要有 head 的上一个节点 pre,以便翻转完后把子链表再接回 pre。此时需要考虑一个特殊条件就是第一个子链表头节点head无pre节点,所以这里可以新建一个节点,把它接到链表的头部,让它作为 pre 的初始值,这样 head 前面就有了一个节点,我们就可以避开链表头部的边界条件。这么做还有一个好处,就是之后返回链表时,无论之后链表有没有翻转,它的 next 指针都会指向正确的头节点。那么我们只要返回它的下一个节点就好了。至此,问题解决。
代码如下:
const myReverse=(head,tail)=>{
//列表翻转
let prev=tail.next; //记录翻转后链表头节点的前一个节点
let p=head;
while(prev!==tail){
const nex=p.next;
p.next=prev;
prev=p;
p=nex;
}
return [tail,head];
}
var reverseKGroup=function (head,k){
//总而言之,一个虚节点hair用来记录整个链表,一个pre记录上一段的尾节点,一个head记录正在翻转的k组的头节点,一个tail记录正在翻转的k组的尾节点
const hair=new ListNode(0);
hari.next=head;
let pre=hair;
while(head){
let tail=pre;
//查看数部分长度是否大于等于k
for(let i=0;i<k;i++){
tail=tail.next;
if(!tail){
return hair.next;
}
}
const nex=tail.next;
[head,tail]=myReverse(head,tail);
//把子链表重新接回原链表
pre.next=head;
tail.next=nex;
pre=tail;
head=tail.next;
}
return hair.next;
};
二、206 反转链表
题目描述
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
解题思路
1、头插法
a、新建一个头节点dummyhead作为翻转后链表的头节点;
b、令head和next分别指向原链表的头节点及其下一个节点;
c、交换节点,令head.next=dummyhead.next;dummyhead.next=head;再将head和next节点分别向后移动一个节点,直到链表结束。
代码如下:
var reverseList=function(head){
const dummyhead=new ListNode(0,null);
let next=head.next;
while(head){
head.next=dummyhead.next;
dummyhead.next=head;
head=next;
next=head.next;
}
return dummyhead.next;
}
2、迭代法
a、设置三个指针prev、cur、next,分别表示当前节点的前一个节点、当前节点及当前节点的后一个节点;
b、让当前指针cur.next=prev;prev、cur和next后移,直到cur为null。
代码如下:
var reverseList(head){
let prev=null;
let cur=head;
let next=null;
while(cur){
next=cur.next; //next指针后移一位
cur.next=prev;
prev=cur;
cur=next;
}
return prev;
};
3、递归
这里参考的是别人的思路,原po主讲的很清楚,我就直接照搬了。参考链接
var reverse=function(head){
//递归终止条件
if(head==null||head.next==null) return head;
//递归到最后一个节点,再从后向前进行反转
const newhead=reverse(head.next);
//反转
head.next.next=head;
//断开原有指向,链表的最后节点指向null
head.next=null;
return newhead;
};