题目
题解
反转整个链表是容易的,但目前问题变成了翻转K个一组结点,那么如何将反转后的子链表和原链表连接呢?官方题解直接用了模拟的方法。
细节比较多,代码很容易就会写的冗杂。
翻转K个结点如图所示:
保存head前一个结点和tail后一个结点,
翻转结点,
翻转后重新连接结点,
代码如下:
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy=new ListNode(0,head);//虚拟头结点
ListNode pre=dummy;
ListNode tail=dummy;
while(head!=null){
//tail移动到该组末尾,若不够k个,则直接返回
for(int i=0;i<k;i++){
tail=tail.next;
if(tail==null)
return dummy.next;
}
//翻转该组
ListNode nex=tail.next;
ListNode[] group=reverse(head,tail);
head=group[0];
tail=group[1];
//重新和原链表连接
pre.next=head;
tail.next=nex;
pre=tail;
head=pre.next;
}
return dummy.next;
}
//翻转一个子链表,并且返回新的头与尾
public ListNode[] reverse(ListNode head,ListNode tail){
ListNode pre=tail.next;
ListNode p=head;
while(pre!=tail){
ListNode nex=p.next;
p.next=pre;//null<-1<-2<-3,指针反转
pre=p;//p和pre均向后移动一位
p=nex;
}
return new ListNode[]{tail,head};
}
}
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)