力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
头插法
将其分成已经反转、正在反转和未反转三个部分。为了方便循环,我们可以先遍历一遍数组,统计一下元素数量len,确定要分几组n=len/k,然后将其反转
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode cur = head;
int len = 0;
while(cur != null) {
len++;
cur = cur.next;
}
int n = len/k;
ListNode pre = dummy;
cur = head;
for(int i=0;i<n;i++) {
for(int j=0;j<k-1;j++) {
ListNode next = cur.next;
cur.next = cur.next.next;
next.next = pre.next;
pre.next = next;
}
pre = cur;
cur = cur.next;
}
return dummy.next;
}
}
穿针引线法
首先,因为要分组反转,我们就一组一组的处理,将其分成已经反转、正在反转和未反转三个部分,同时为了好处理头结点,我们新建一个虚拟头结点。
之后我们直接遍历,根据是否为K个找到四个关键位置,并用变量pre、start、end和next标记,如下:
接着我们就可以对上图中颜色部分进行反转了
完成之后,我们要将裁下来的部分再缝到原始链表上,这就需要调整指针指向了,同样注意指针的指向:
最后调整一下几个变量的位置,为下一次做准备:
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy;
ListNode end = dummy;
while (end.next != null) {
//找到要处理的区间的末尾
for (int i = 0; i < k && end != null; i++){
end = end.next;
}
if (end == null){
break;
}
//将要处理的区间裁剪下来
ListNode start = pre.next;
ListNode next = end.next;
end.next = null;
//执行反转
pre.next = reverse(start);
// 上面pre.next和下面start.next两个指针是为了将反转的区间缝补回去
start.next = next;
//调整指针,为下一组做准备
pre = start;
end = pre;
}
return dummy.next;
}
private ListNode reverse(ListNode head) {
ListNode pre = null;
ListNode curr = head;
while (curr != null) {
ListNode next = curr.next;
curr.next = pre;
pre = curr;
curr = next;
}
return pre;
}