K 个一组翻转链表
描述
给你链表的头节点 head ,每 k **个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k **的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
分析
- 以k个元素为一组去找。初始化p1,p2,作为组的首尾指针。
- 若找到k个,直接对着k个元素进行反转(这里需要注意把p2.next置位null),保存反转后的首尾指针到集合list,用于后续的连接
- 若没有找到k个,直接把当前这组的首尾指针保存到集合list
- 根据保存的首尾指针,重新合并链表。
代码
public static class Info {
ListNode head;
ListNode tail;
public Info(ListNode head, ListNode tail) {
this.head = head;
this.tail = tail;
}
}
public ListNode reverseKGroup(ListNode head, int k) {
List<Info> res = new ArrayList<>();
ListNode p1 = head;//首
ListNode p2 = head;//尾
while (p2 != null) {
int num = 1;
while (p2.next != null && num < k) {
p2 = p2.next;
num++;
}
ListNode next = p2.next;//需要记录下一组的起点
Info info;
if (num == k) {//有k个
p2.next = null;//这里必须要切断,再去反转,否则会反转整个链表
ListNode nHead = reverseList(p1);//反转这个区间内的链表
info = new Info(nHead, p1);
} else {//不足k个
info = new Info(p1, p2);
}
res.add(info);
p2 = next;
p1 = p2;
}
/*串联*/
Info info = res.get(0);
ListNode newHead = info.head;
ListNode tail = info.tail;
for (int i = 1; i < res.size(); i++) {
Info tList = res.get(i);
tail.next = tList.head;
tail = tList.tail;
}
return newHead;
}
private ListNode reverseList(ListNode p1) {
if (p1.next == null) {
return p1;
}
ListNode listNode = reverseList(p1.next);
p1.next.next = p1;
p1.next = null;
return listNode;
}