描述
将给出的链表中的节点每 k 个一组翻转,返回翻转后的链表
如果链表中的节点数不是 k 的倍数,将最后剩下的节点保持原样
你不能更改节点中的值,只能更改节点本身。
数据范围: 0≤n≤2000 , 1≤k≤2000 ,链表中每个元素都满足 0≤val≤1000
要求空间复杂度 O(1),时间复杂度 O(n)
例如:
给定的链表是 1→2→3→4→5,1→2→3→4→5
对于 k=2 , 你应该返回 2→1→4→3→5,2→1→4→3→5
对于 k=3 , 你应该返回 3→2→1→4→5,3→2→1→4→5
示例1
输入:
{1,2,3,4,5},2
返回值:
{2,1,4,3,5}
示例2
输入:
{},1
返回值:
{}
这道题的难度点在于将单次翻转的题链表之指定区间翻转变成了多次的翻转
所以在遍历整个链表的时候,需要有个计数器来记录是否已经走完一轮区间了,那么当走完一轮区间之后,将该轮的结点进行翻转
这里有个关键点是第4步,需要先将当前结点先指向下一个结点,而不是在每轮遍历之后再做
---因为如果不先指向后一个结点,那么在后续断链的操作时,就会丢失后续的结点,那么后续的遍历也无从谈起了,所以先指向后续结点,再断链。
还有最后一步计数器的累加num++,是因为只有将前面的翻转逻辑处理完成之后才能变动num,不然0的作用就失效了。
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode类
* @param k int整型
* @return ListNode类
*/
public ListNode reverseKGroup (ListNode head, int k) {
//1.判空
if (head == null || head.next == null)
return head;
//2.设置一个头结点
ListNode dummpNode = new ListNode(0);
dummpNode.next = head;
ListNode curNode = head;
ListNode preNode = dummpNode;
ListNode leftNode = null;
ListNode rightNode = null;
int num = 1;//用计算每一次区间内的已经处理的结点个数
//3.遍历整个链表
while (curNode != null) {
//因为要先判断是否达到k个结点才倒置,所以只是先统计,后倒置
if (num == 1) {
leftNode = curNode;
}
if (num == k) {
rightNode = curNode;
num = 0;//置0是为了方便我们后续知道以及统计完一轮的信息了
}
//4.将curNode指向下一个结点
curNode = curNode.next;
if (num == 0) {
//5.前后断链
preNode.next = null;
rightNode.next = null;
//6.翻转后重新续接
preNode.next = reverse(leftNode);
leftNode.next = curNode;
preNode = leftNode;
}
num++;
}
return dummpNode.next;
}
public ListNode reverse(ListNode head) {
ListNode newHead = null;
ListNode next = null;
ListNode cur = head;
while (cur != null) {
next = cur.next;
cur.next = newHead;
newHead = cur;
cur = next;
}
return newHead;
}
}