31.K个一组翻转链表
给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
示例1:

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

输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]
提示:
- 链表中的节点数目为 n
- 1 <= k <= n <= 5000
- 0 <= Node.val <= 1000
代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
//创建一个哑结点,这个哑结点就是避免边界问题和报错
ListNode newListNode = new ListNode(0,head);
//创建一前一后两个指针,用来截取每一个k长度的链表进行分次反转
ListNode pre = newListNode;
ListNode end = newListNode;
//如果这里不明白为什么是end.next,那么可以看看后面的逻辑再来看这个解释
//因为对于end你已经在截取k长度的时候判定过了,如果不满足就会跳出,但是如果end长度为k的时候呢?
//而end所在的位置是下一个起始位置的前一个节点,所以当end.next==null的时候
//表示已经到了尾部不用再循环了
while(end.next != null){
//k长链表截取,这里的k不用解释,end.next的作用是防止为null报错,
//不满足条件直接退出当前截取的循环,然后交给下面if判断跳出总的while循环
for(int i = 0; i < k && end != null;i++){
end = end.next;
}
//判定是否需要跳出循环
if(end == null){
break;
}
//确定开始反转的头结点
ListNode start = pre.next;
//记录下一个节点,作为下次反转的起始节点,因为当前需要把end.next置空
//进行反转链表的操作
ListNode nextStart = end.next;
end.next = null;
//反转链表并将反转好的值给pre.next,
//因为反转后star刚好变成当前pre的下一个node
pre.next = tranfer(start);
//将反转好的链表和后续未反转的链接好
start.next = nextStart;
//重置start的起始位置开始下一轮的转换
pre = start;
end = start;
}
return newListNode.next;
}
//反转链表
private ListNode tranfer(ListNode head){
//初始化一个尾结点
ListNode l = null;
while(head != null){
ListNode temp = head.next;
head.next = l;
l = head;
head = temp;
}
return l;
}
}

浙公网安备 33010602011771号