1、前言

2、思路
首先需要一个反转链表函数,然后在此基础上递归。
需要注意的是,我们是按照 k 去反转,可以使用递归的方法来做,非递归遍历也行。非递归可以参照使用反转链表 m 到 n 之间的数的函数,然后稍加改造。
对于这类题目,最重要的还是用非递归最符合直觉的方法来做。但是非递归就涉及到一个细节问题,就可能就写岔了。所以最重要的要素是把链表反转的头插法先写好,然后从 dummy 出发开始 k 个,然后将链表断开就很好反转了,断开之前记得先记录下个头。断开之后,p 指向 head 的节点,反转后它就变成尾节点。后面不写了,反转记住就这样做。
3、代码
非递归:
class Solution {
/**
* 使用反转区间链表的方法,一个区间一个区间的反转,对于最后不足的,直接不反转
*/
ListNode reverseKGroup(ListNode head, int k) {
if(head == null || k <= 0){
return head;
}
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode p = dummy, lastHead = dummy;
while(p != null){
for(int i = 0; i < k; i++){
if(p != null){
p = p.next;
}
}
if(p == null){
return dummy.next;
}
ListNode temp = p.next;
p.next = null;
p = head;
lastHead.next = reverse(head);
lastHead = p;
head = temp;
p.next = head;
}
return dummy.next;
}
private ListNode reverse(ListNode head){
if(head == null){
return head;
}
ListNode dummy = new ListNode(-1);
ListNode p = head;
while(p != null){
ListNode temp = p.next;
ListNode next = dummy.next;
dummy.next = p;
p.next = next;
p = temp;
}
return dummy.next;
}
}
递归:
class Solution {
ListNode reverseKGroup(ListNode head, int k) {
if (head == null) return null;
// 区间 [a, b) 包含 k 个待反转元素
ListNode a = head, b = head;
for (int i = 0; i < k; i++) {
// 不足 k 个,不需要反转,base case
if (b == null) return head;
b = b.next;
}
// 反转前 k 个元素
ListNode newHead = reverse(a, b);
// 递归反转后续链表并连接起来
a.next = reverseKGroup(b, k);
return newHead;
}
/** 反转区间 [a, b) 的元素,注意是左闭右开 */
ListNode reverse(ListNode a, ListNode b) {
ListNode pre = null, cur = a, next = a;
// while 终止的条件改一下就行了
while (cur != b) {
nxt = cur.next;
cur.next = pre;
pre = cur;
cur = nxt;
}
// 返回反转后的头结点
return pre;
}
}
网友评论