题目
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明 :
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
思路
1>使用辅助空间将每次反转后的头结点存起来,最后串起来
时间复杂度O(N),空间复杂度O(N/k)
2>暴力解
遍历链表,每K个一组反转,需要保留每组的头结点和反转之后的尾节点,头结点用于反转该组,反转之后的尾节点用于连接下一组反转之后的头结点,将整个链表串起来,在遍历时判断第一次反转,保留反转之后的头结点用于返回。
时间复杂度O(N),空间复杂度O(1)
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
if(head == null || head.next == null){
return head;
}
//小于一组检验
ListNode tmp = head;
int i = 1;
while(tmp.next != null){
tmp = tmp.next;
i++;
}
if(i < k){
return head;
}
//每组的头结点(用于反转)
ListNode GroupFirstNode = head;
//前一组反转后的尾节点(用于后一组反转完成后连接起来)
ListNode preGroupNode = null;
//保留第一组反转之后的头结点 用于返回
ListNode res = head;
int index = 1;
while(head != null){
//完整一组 开始反转
if(index % k == 0){
//保留下一组的头结点
ListNode next = head.next;
//切断当前组的后序节点
head.next = null;
//反转当前组
ListNode GroupNewNode = reverse(GroupFirstNode);
//第一组 用于保留头结点返回
if(index == k){
res = GroupNewNode;
}
//将上一组反转后的尾节点和当前组反转后的头结点相连
if(preGroupNode != null){
preGroupNode.next = GroupNewNode;
}
//获得反转后的尾节点
while(GroupNewNode.next != null){
GroupNewNode = GroupNewNode.next;
}
//更新尾节点
preGroupNode = GroupNewNode;
//更新下一组的头结点
GroupFirstNode = next;
head = next;
index++;
}else{
head = head.next;
index++;
}
}
//连接最后不足一个分组的数据
ListNode cur = res;
while(res.next != null){
res = res.next;
}
res.next = GroupFirstNode;
return cur;
}
//反转链表
public ListNode reverse(ListNode node){
ListNode pre = null;
while(node.next != null){
ListNode next = node.next;
node.next = pre;
pre = node;
node = next;
}
node.next = pre;
return node;
}
}