前言
经过两大关的学习,hxdm一定都有所收获吧(doge),我们从什么是链表,到链表是如何构造的,再到一系列关于链表的拓展或延伸问题,最后我们来到了这里。相信大家看到之前一看就脑阔疼的链表相关问题,现在都有自己的理解了,虽然可能还是不能完整的写出结果,但大致的思路已经理清楚了,这就是进步,持续的一丢丢的进步,其效果也是显而易见的!
进入正题,我们来说说这个K个一组反转的问题!
题目介绍
题目详情:
思路引导
- 首先,我们需要遍历整个链表来确定链表的长度。
- 如果链表的长度小于 k,则直接返回原链表,因为无需进行翻转。
- 否则,我们需要将链表分成若干组,每组包含 k 个节点。对于每一组,我们需要将其内部的节点进行翻转,然后将每组的头尾连接起来,得到翻转后的链表。
- 最后,将每组的头尾连接起来,并返回翻转后的链表。
我们在之前学习两两交换链表中地结点时使用的方法有头插法,还有递归法(没有具体讲解)。对于本题具体的解法,我们可以参考两两交换的题解,即使用虚拟头结点进行头插法!
下面我们来进一步深入此场景~
解法1(迭代法)穿针引线法
乍一看,这道题不和两两反转一样吗,只不过k=2吗,是也不是,因为k不确定,要考虑的场景较多,比如反转后首尾的连接,k的大小等条件。具体实现来说是有一定的困难的。
还是老样子,上图(俺的图图呢?!哦,在这啊!)
(能力有限告辞了各位!! 图只是我片面的理解,各位佬自己画一遍会更理解!)
根NB的图在这里:(教官的图)
代码如下:
public ListNode reverseKGroup(ListNode head, int k) {
// 创建一个虚拟头节点,方便处理边界情况
ListNode dummy = new ListNode(0);
dummy.next = head;
// pre 表示当前待反转链表的前一个节点
// end 表示当前待反转链表的尾节点
ListNode pre = dummy;
ListNode end = dummy;
while (end.next != null) {
// 让 end 走 k 步,找到待反转链表的尾节点
for (int i = 0; i < k && end != null; i++) {
end = end.next;
}
// 如果 end 为 null,说明剩余节点不足 k 个,直接结束循环
if (end == null) {
break;
}
// 记录待反转链表的头节点
ListNode start = pre.next;
// 记录下一组待反转链表的头节点
ListNode next = end.next;
// 将待反转链表与下一组链表断开
end.next = null;
// 反转待反转链表,并将反转后的链表与原链表连接起来
pre.next = reverseLinkedList(start);
start.next = next;
// 更新 pre 和 end 的位置,准备处理下一组链表
pre = start;
end = pre;
}
return dummy.next;
}
// 链表反转操作
private ListNode reverseLinkedList(ListNode head){
ListNode pre = null;
ListNode cur = head;
while(cur!= null){
ListNode temp = cur.next;
cur.next = pre;
pre = cur;
cur =temp;
}
return pre;
}
解法2(头插法)
和上面一种差不多的解法,但容易理解些
上图
上代码
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummyNode = new ListNode(-1);
dummyNode.next = head;
ListNode cur = head;
int len = 0; // 先计算出链表的长度
while (cur != null) {
len++;
cur = cur.next;
}
int n = len / k; // 计算出有几组
ListNode pre = dummyNode;
cur = head;
for (int i = 0; i < n; i++) {
for (int j = 0; j < k - 1; j++) {
ListNode next = cur.next;
cur.next = cur.next.next;
next.next = pre.next;
pre.next = next;
}
pre = cur;
cur = cur.next;
}
return dummyNode.next;
}
解法3(递归)
直接上代码了,这个递归还是比较好李姐的!
public ListNode reverseKGroup(ListNode head, int k) {
int count = 0;
ListNode cur = head;
// 计算长度
while(cur != null){
count++;
cur = cur.next;
}
// 如果长度小于k直接返回头结点
if(count < k){
return head;
}
ListNode pre = null;
ListNode tmp = null;
cur = head;
for(int i = 0;i < k;i++){
tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
head.next = reverseKGroup(tmp,k);
return pre;
}
OK,链表的学习就到这里了,后续会持续更新关于一些场景题的讲解,如有遗漏和错误,还望指正。大家一起学习进步~
加油,奥利给!!!!!!!!