题目描述

难度:困难

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

示例 1:

img

输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]

示例 2:

img

输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]

提示:

  • 链表中的节点数目为 n
  • 1 <= k <= n <= 5000
  • 0 <= Node.val <= 1000

**进阶:**你可以设计一个只用 O(1) 额外内存空间的算法解决此问题吗?

思路

因为个人不习惯用递归,所以这里先确定循环次数、循环停止条件。

外层循环次数:round=size/k;

好吧循环停止条件还得后面展开了才好确定(

易知(?)一组翻转后,原本最前的节点(翻转后最后的节点)的next将指向下一组的最前节点,原本最后的节点(翻转后最前的节点)作为前一组最后节点的next节点,中间则正常翻转。

所以这里先确定一个start、end节点,分别是这组的第一个节点和下一组的第一个节点(作为循环停止条件)

然后一个常用的双指针prev、cur,当cur==end时组内循环停止

最后整一个prevStart,一开始作为虚拟头,后面指向翻转后上一组最后的节点。

1710252583249

代码

class Solution {
public int getSize(ListNode head){
int size=0;
ListNode cur=head;
while(cur!=null){
size++;
cur=cur.next;
}
return size;
}
public ListNode reverseKGroup(ListNode head, int k) {
int size=getSize(head);
int round=size/k;
ListNode newHead=new ListNode();
ListNode start=head;
ListNode end=null;
ListNode prevStart=newHead;
for(int i=0;i<round;i++){
ListNode tmp=start;
for(int j=0;j<k;j++){
tmp=tmp.next;
}
end=tmp;

ListNode prev=start;
ListNode cur=prev.next;


start.next=end;

while(cur!=end){
ListNode tmpNode=cur.next;
cur.next=prev;
prev=cur;
cur=tmpNode;
}
prevStart.next=prev;
prevStart=start;
start=end;
}
return newHead.next;
}
}