题目解析:(题目来源:25. K 个一组翻转链表)
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
进阶:
你可以设计一个只使用常数额外空间的算法来解决此问题吗?
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
这道题目是反转链表的升级,它指定了反转链表的个数,当个书不够时直接原样返回。看一下进阶说的是常数额外空间去解决,意思就是让我们不要开辟额外的空间,直接对链表进行操作。这种重叠性子问题,当然是递归呀~
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode nodeNext = head;
//积累递归结点数量所做的标记,不能超过k
int restNum = 0;
while(restNum < k){
restNum ++;
if(nodeNext == null){
return head; //退出循环的条件
}
nodeNext= nodeNext.next;
}
ListNode newNode = reverseKGroup(nodeNext , k); //递归方程
ListNode res = reverseNGroup(head , k);
head.next = newNode;
return res;
}
private ListNode reverseNGroup(ListNode head , int n){ //单次递归的操作
ListNode pre = null;
ListNode cur = head;
while(n > 0){
n--;
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
思路很清晰,每个单次递归元素由一个传统的一个结点变成了k个结点。
(一)实现取地k个结点的操作就是最开始那个while循环。但是为了避免空指针,要讨论特殊情况:当剩余结点数量不够k个时,题目也给了我们处理方法,就直接原样返回,我们直接返回head就行了。
(二)然后就是递归对每组结点进行单次反转链表操作,最后把组与组之间连接(head.next = newNode),返回最终结果。
(三)对于递归的理解,这位大佬的文章讲的非常详细:宏观视角看递归