题目描述:
K 个一组翻转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
题目链接:click me !
说明:
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
思路一:
这道题级别虽然是“困难”,但只要想通了就很简单,模拟一下过程就可以得到结果。
- 我们先给一个哑结点(dummy)用来指向链表,最后返回dummy.next
- 在每一次翻转子链表的过程中我们都需要维护4个指针:prev、start、end、next
- prev的作用是用来 连接 已翻转链表和待翻转链表,start 和 end 是用来翻转每个子链表,next 是用来记录下一个待翻转子链表的头部
- 我们把翻转每个子链表的任务交给reverse()来完成,返回每个子链表翻转后的头结点
- 每次翻转完成之后我们都需要维护以上的4个指针
主要步骤如下:
每次翻转都经过上述4步,直到end.next == null,结束翻转,返回dummy.next
Java代码实现:
// 结点类
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class Solution01 {
public static ListNode reverseKGroup(ListNode head, int k) {
// 给一个哑结点,用来指向列表的头部
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode prev = dummy;
ListNode end = dummy;
while (end.next != null) {
int n = k;
// 找到每个子链表的最后一个元素
while (end != null && (n--) > 0) end = end.next;
if (end == null) break; // 子链表中元素个数不足K个
ListNode start = prev.next; // start指向当前待翻转子链表的头部
ListNode the_next = end.next; // 记录下一个子链表的头结点
end.next = null; // 把将要翻转的子链表和下一个待翻转的子链表断开
// 翻转当前链表
prev.next = reverse(start);
// 维护prev、start、end、next
// 将翻转后的链表和待翻转链表连起来
start.next = the_next;
prev = start;
end = start;
}
return dummy.next;
}
// 翻转子链表
private static ListNode reverse(ListNode curr) {
// 确保curr不为空
ListNode prev = null;
ListNode next;
while (curr != null) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
}
思路二: 递归
K个一组翻转链表,具体到每一段,其实就是一个简单的翻转链表的问题
所以我们只需要将每一个段翻转的头结点返回,拼接到前一段的翻转后的尾结点即可
Java实现:
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
if(head==null) return null;
ListNode cur = head;
int i = k;
// 先遍历找到下一段的开头
while(i>0&&cur!=null){
cur = cur.next;
i--;
}
// 如果没有到k个,那么原顺序返回
if(i>0) return head;
// 关键在于这个位置,返回值拼接到当前段翻转后的尾结点即可
// 而尾结点就是原链表在当前段的头
ListNode pre = reverseKGroup(cur,k);
cur = head;
i = k;
while(i>0){
ListNode tmp = cur.next;
cur.next= pre;
pre = cur;
cur = tmp;
i--;
}
return pre;
}
}