难度:困难
题目:
给你链表的头节点
head
,每k
个节点一组进行翻转,请你返回修改后的链表。
描述:
k
是一个正整数,它的值小于或等于链表的长度。如果节点总数不是k
的整数倍,那么请将最后剩余的节点保持原有顺序。你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
示例一:
输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]
示例二:
输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]
提示:
- 链表中的节点数目为
n
1 <= k <= n <= 5000
0 <= Node.val <= 1000
进阶:你可以设计一个只用 O(1)
额外内存空间的算法解决此问题吗?
Related Topics
- 递归
- 链表
重点!!!解题思路
第一步:
先创建前驱节点hair(省了一步特判)
K个一组反转链表,假设为2个一组,那么我们要将这两个节点反转
首先做的就是先确定每次选择的两个节点
第二步:
将这两个待反转的节点传入一个方法中进行交换,
当交换完后应该是2->1->3->4->5
为了使下一次3 4节点交换完不和前面的节点失联
我们需要待反转链表的前一个节点
这样每次反转完成,前后节点都不会丢失
第三步:
最后我们返回hair的下一个节点,即为整个链表
源码:
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode hair=new ListNode(-1,head);
ListNode pre=hair;
ListNode tail=null;
while (head!=null){ //当头部节点不为空时才能进行一下操作
tail=pre; //首先让tail在pre节点位置
for (int i=0;i<k;i++){ //经过循环 使tail到待反转链表的末端
tail=tail.next;
if(tail==null){ //每循环一次 当tail等于空了 就说明不够一组了 直接返回反转完的链表
return hair.next;
}
}
ListNode[] revers = reverse(head,tail); //将待反转链表的第一个节点和最后一个节点传进反转方法中
head=revers[0]; //让head节点等于反转链表的第一个位置 便于理解
tail=revers[1]; //让tail节点等于反转链表的最后一个位置 便于理解
pre.next=head; //pre为前驱节点 让他和head相连
pre=tail; //这里让pre指向下一组待反转链表的前一个节点
head=pre.next; //head节点依然是pre的下一个节点
}
return hair.next;
}
public ListNode[] reverse(ListNode head,ListNode tail){
ListNode pre=tail.next,cur=head,next=null; //定义一个新节点在位置在tail后面,这个操作可以使待反转的链表反转前能和后面的链表相连 不会断开
while (pre!=tail){
next=cur.next;
cur.next=pre;
pre=cur;
cur=next; //让cur每次都在向后移动 当pre移动到tail位置时 反转完成
}
return new ListNode[]{tail,head};//当反转完成时tail在反转链表的最前面,head在反转链表的最后面
}
}
运行结果:
如果您还有什么疑问或解答有问题,可在下方评论,我会及时回复。