25. K 个一组翻转链表

递归+双指针

image.png

根据算法思路:

  1. 先反转以head开头的k个元素

image.png

  1. 将第k+1个元素作为head递归调用reverseGroup函数

image.png

  1. 将上面两个过程的结果连接起来

image.png

如何反转以head开头的k个元素:
初始化三个指针分别指向pre、current、next三个节点,让pre指向null,current和next指向节点a。循环翻转节点直到current指向节点b,每次循环,next应该是current的下一个节点,然后将current的下一节点指向前一个来完成反转,最后更新指针位置。
8.gif

  1. //反转a到b之间的节点
  2. private ListNode reverse(ListNode a, ListNode b){
  3. //前一个、当前、后一个节点
  4. ListNode pre = null, cur = a, nxt = a;
  5. while(cur != b){
  6. nxt = cur.next;
  7. //逐个节点反转
  8. cur.next = pre;
  9. //更新指针位置
  10. pre = cur;
  11. cur = nxt;
  12. }
  13. //返回反转后的头节点
  14. return pre;
  15. }
  16. public ListNode reverseKGroup(ListNode head, int k) {
  17. if(head == null) return null;
  18. //区间[a, b) 包含k个待反转的元素
  19. ListNode a, b;
  20. a = b = head;
  21. //让b到达第k个节点
  22. for(int i = 0; i < k; i++){
  23. //如果不足k个,则不需要反转,base case
  24. if(b == null) return head;
  25. b = b.next;
  26. }
  27. //翻转前k个元素
  28. ListNode newHead = reverse(a, b);
  29. //递归反转后续链表并连接起来
  30. a.next = reverseKGroup(b, k);
  31. return newHead;
  32. }