K个节点的组内逆序调整

给定一个单链表的头节点head,和一个正数k
实现k个节点的小组内部逆序,如果最后一组不够k个就不调整。
例子:
调整前:1->2->3->4->5->6->7->8, k=3
调整后:3->2->1->6->5->4->7->8
 
代码实现:
 1 package com.cy.class04;
 2 
 3 /**
 4  * 测试连接:https://leetcode.com/problems/reverse-nodes-in-k-group/
 5  */
 6 public class Code04_ReverseNodesInKGroup {
 7 
 8     // 不要提交这个类
 9     public static class ListNode {
10         public int val;
11         public ListNode next;
12     }
13 
14     public static ListNode reverseKGroup(ListNode head, int k) {
15         ListNode start = head;
16         ListNode end = getKGroupEnd(start, k);
17         //第一组都没有凑齐都不用逆序了直接返回老head
18         if (end == null) {
19             return head;
20         }
21 
22         //后面该怎么调整怎么调整,这个head就是要返回的,不要动它了。
23         head = end;
24         reverse(start, end);
25         //lastEnd:上一组的结尾节点
26         ListNode lastEnd = start;
27         while (lastEnd.next != null) {
28             start = lastEnd.next;
29             end = getKGroupEnd(start, k);
30             if (end == null) {
31                 return head;
32             }
33             reverse(start, end);
34             lastEnd.next = end;
35             lastEnd = start;
36         }
37         return head;
38     }
39 
40     /**
41      * 给定链表的开始节点,数够k个,把数到的节点返回
42      * 该组内元素不够k个,就返回null
43      */
44     public static ListNode getKGroupEnd(ListNode start, int k) {
45         while (--k != 0 && start != null) {
46             start = start.next;
47         }
48         return start;
49     }
50 
51     public static void reverse(ListNode start, ListNode end) {
52         end = end.next;
53         ListNode pre = null;
54         ListNode cur = start;
55         ListNode next = null;
56         while (cur != end) {
57             next = cur.next;
58             cur.next = pre;
59             pre = cur;
60             cur = next;
61         }
62         start.next = end;
63     }
64 }

 

演算草图: 

思路是什么?
1.假设链表分成了三组:a~b,c~d,e~f,假如第二组逆序好了成了d~c,第一组逆序好了成了b~a,第三组逆序好了成了f~e,那么就要修改指向:将a的next指向d,c的next指向f。
 
getKGroupEnd函数:给定一个开始节点,数到k个,返回这个最后数到的节点,其实就是从start开始返回第k个节点。
这里面其实是有边界条件考虑的,因为可能该组内元素个数不满k个,就数到null了:
 
reverse方法解释:
经过reverse之后变成:
s之前的是啥,不管。从s开始。将a~d之间进行逆序:
最后逆序完成的效果见下图:而且逆序完成之后,a已经指向f了,但是没有任何节点指向a。
画图工具可以复现这个逆序过程:
reverseKGroup方法的解释:
草图1:
运行到head = end时,这个head就是要返回的,变成这样:
运行到24行,reverse(start, end)时变成这样:
此时,a - b - c这组的结尾节点就是start,即a节点。
27行:上组结尾节点a的下个节点不为null,进入while循环。28行:start来到d节点,见下图:
30行:end为f节点,不为null,进入33行:reverse(start, end),变成如下:
运行到34行:lastEnd.next = end;将上组的末尾节点的下个节点指向修改,a本来是指向d的,改成了a指向f:
并且lastEnd来到d节点:
继续运行,g、h不够k=3个,end为null,直接返回head,while循环中断,也就是返回c节点,程序结束。
什么时候会while循环完毕,执行到最后return head结束呢?----所有节点个数正好是k的整数倍。
 

总结:

1.该题在leetcode中属于难度级别hard,很麻烦,要对于整个函数的设计能力非常强才行。
2.先想好整个过程,然后再是把想法变成code,其实挺难的。它不在于算法,而是在于你的coding能力强不强。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
---
posted on 2025-05-01 17:14  有点懒惰的大青年  阅读(16)  评论(0)    收藏  举报