题目描述

给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序。

示例 :
给定这个链表:1->2->3->4->5
k = 2 时,应当返回: 2->1->4->3->5
k = 3 时,应当返回: 3->2->1->4->5

说明 :

  • 你的算法只能使用常数的额外空间。

  • 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

题解

逆转单链表

参考:

第一个逆转后就成了最后一个。然后遍历每个 node,把它放到链表的首位,最后一个就么成了第一个。
因为有放到链表首位的操作,所以还需要一个 dummy 头节点,下面是逆转单链表的代码:

  1. /// <summary>
  2. /// Reverse a link list between begin and end exclusively
  3. /// Example, a linked list:
  4. /// 0->1->2->3->4->5->6
  5. /// | |
  6. /// begin end
  7. ///
  8. /// after call begin = Reverse(begin, end)
  9. ///
  10. /// 0->3->2->1->4->5->6
  11. /// | |
  12. /// begin end
  13. /// </summary>
  14. /// <param name="begin"></param>
  15. /// <param name="end"></param>
  16. /// <returns>The reversed list's 'begin' node, which is the precedence of node end</returns>
  17. private static ListNode Reverse(ListNode begin, ListNode end)
  18. {
  19. var curr = begin.next;
  20. var prev = begin;
  21. var first = curr;
  22. while (curr != end)
  23. {
  24. var next = curr.next;
  25. curr.next = prev;
  26. prev = curr;
  27. curr = next;
  28. }
  29. begin.next = prev;
  30. first.next = curr;
  31. return first;
  32. }

主体方法:

  1. public static ListNode ReverseKGroup(ListNode head, int k)
  2. {
  3. if (head?.next == null || k == 1) return head;
  4. var dummy = new ListNode(0) {next = head};
  5. var begin = dummy;
  6. var i = 0;
  7. while (head!=null)
  8. {
  9. i++;
  10. if (i % k == 0)
  11. {
  12. begin = Reverse(begin, head.next);
  13. head = begin.next;
  14. }
  15. else
  16. {
  17. head = head.next;
  18. }
  19. }
  20. return dummy.next;
  21. }