题目连接

示例

给定一个单链表 L 的头节点 head ,单链表 L 表示为:
L0 → L1 → … → Ln-1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 1:
image.png
输入: head = [1,2,3,4]
输出: [1,4,2,3]

示例 2:
image.png
输入: head = [1,2,3,4,5]
输出: [1,5,2,4,3]

解题思路

重排后为:第一个,倒数第一个,第二个,倒数第二个,第三个,倒数第三个。。。

整体思路就是:

  • 首先,找到链表的中间节点,方法如上述的#876题;
  • 接着,将链表的后半部分反转,放入如上述的#206题;
  • 然后,将链表的前半部分和链表的后半部分反转后的结果进行合并。

代码

  1. public void reorderList(ListNode head) {
  2. if (head == null) {
  3. return;
  4. }
  5. // 获得中间节点
  6. ListNode mid = findMid(head);
  7. // 中间节点之后的部分进行反转
  8. ListNode head2 = mid.next;
  9. mid.next = null;
  10. head2 = reverseList(head2);
  11. // 合并
  12. ListNode head1 = head;
  13. mergeList(head1, head2);
  14. }
  15. // LeetCode 876
  16. private ListNode findMid(ListNode head){
  17. ListNode slow = head;
  18. ListNode fast = head;
  19. while (fast.next != null && fast.next.next != null) {
  20. slow = slow.next;
  21. fast= fast.next.next;
  22. }
  23. return slow;
  24. }
  25. // LeetCode 206
  26. private ListNode reverseList(ListNode head){
  27. ListNode prev = null;
  28. ListNode cur = head;
  29. while (cur != null) {
  30. ListNode nextNode = cur.next;
  31. cur.next = prev;
  32. prev =cur;
  33. cur = nextNode;
  34. }
  35. return prev;
  36. }
  37. private void mergeList(ListNode head1, ListNode head2) {
  38. ListNode next1 = null;
  39. ListNode next2 = null;
  40. while (head1 != null && head2 != null) {
  41. next1 = head1.next;
  42. next2 = head2.next;
  43. head1.next = head2;
  44. head1 = next1;
  45. head2.next = head1;
  46. head2 = next2;
  47. }
  48. }