先来看反转一个链表的情况:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode dummy = new ListNode(-1, head);
ListNode cur = head;//不需要pre 直接用dummy就好了
while(cur != null && cur.next != null) {
ListNode tmp = cur.next;
cur.next = tmp.next;
tmp.next = dummy.next;
dummy.next = tmp;
}
return dummy.next;
}
}
反转一组,头节点前一个用dummy表示,尾节点后一个就是null。
K个一组反转与单独反转一组的区别就是:K个中,这一组反转后的链表,还需要与其他的节点相连接。
所以下面的写法就是,对于reverse的方法,两个参数分别是这个链表的 头节点的前一个节点,尾节点的后一个节点 (该方法的reverse可以没有返回值
class Solution {
//start表示要反转的头部的前一个 end表示要反转的结尾的后一个
//接下来 与单纯的反转链表中的对应 start对应dummy end对应结尾的null
void reverse(ListNode start, ListNode end) {
ListNode cur = start.next;
while(cur != end && cur.next != end) {
ListNode tmp = cur.next;
cur.next = tmp.next;
tmp.next = start.next;
start.next = tmp;
}
}
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(-1, head);
ListNode cur = dummy, last = dummy;//cur遍历整个链表 last存储头节点的前一个
int num = 0;
while(cur != null) {
if(num >= k && num % k == 0) {//只有当遍历到k的1.2.3...整数倍时才进行反转
//有个问题:每次反转之后的cur就不是反转后的尾部了(变成头部了)所以要进行转换
// 两种写法:1每次都记录头节点last.next 反转后赋值 2反转后对cur向后走k-1步
// ListNode tmp = last.next;
// reverse(last, cur.next);
// cur = tmp;
// last = cur;
reverse(last, cur.next);
for(int i = 0; i < k - 1; i++) cur = cur.next;//这里 反转后对cur向后走k-1步
last = cur;
}
num++;
cur = cur.next;//每次统计num次数 并cur向后
}
return dummy.next;
}
}