这道题是在基于链表反转的基础上。
开始做的时候,我只能想到将链表进行反转,+递归
但是怎样就行写不出来
后面看了一眼官方的解答,说定义两个指针 来表示需要反转的链表 再用递归
果然最难的还是思路!
上代码:
当然这部分代码写的不是很快,大概大半个小时
class Solution {
//设计一个栈作为常数的额外空间
//知识点————n个结点的链表反转
//思路: 根据k的长度设计一个两个指针 表示 需要反转的位置
public ListNode reverseKGroup(ListNode head, int k) {
if(head==null||k==1) return head;
ListNode pre=head,end=head;
int count=1;
//将end转到反转的末尾
while(count<k){
end=end.next;
++count;
if(end==null){
return pre;
}
}
ListNode tem=reverseKGroup(end.next,k);//进入递归
end.next=null;
ListNode tem2=reverseList(pre);
tem2.next=tem;
/*head=end.next;//更新head位置
end.next=null;//这样只需反转k个
pre=reverseList(pre);//这里返回值是最后一个 设计返回值
//pre.next=reverseKGroup(head,k);//进入递归
return head;*/
return end;
}
public ListNode reverseList(ListNode head){
//这里是进行链表反转————递归
if(head==null||head.next==null) return head;
ListNode tem=reverseList(head.next);
tem.next=head;
head.next=null;
return head;
}
}
剖析一下代码
链表反转部分:
public ListNode reverseList(ListNode head){
//这里是进行链表反转————递归
if(head==null||head.next==null) return head;
ListNode tem=reverseList(head.next);
tem.next=head;
head.next=null;
return head;
}
递归进入到最后一个节点A,(A->B)使后节点A指向前驱结点B(A<-->B)
然后再让A指向为空 (A<--B) 即相当于 B-->A
然后返回A
这样就进入倒数第二次递归,要处理的就是A和A前面的两个结点
这部分递归结束之后返回的是最后一个结点。————如果单反转链表,只需在递归到最后一个结点时,将头结点指向它就行。
反转k一组反转链表时:
这部分是递归的核心部分 大概四五行消耗大部分时间
ListNode tem=reverseKGroup(end.next,k);//进入递归————返回值是处理之后的头结点end.next=null;//将end.next赋予null 便于反转链表
ListNode tem2=reverseList(pre);//tem2是反转之后的尾结点
tem2.next=tem;//因为递归是倒数开始处理 这里相当于是 把前后给连接起来
return end;//返回第一次要处理的头结点