1. 题目描述

给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…

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

示例 1:

  1. 给定链表 1->2->3->4, 重新排列为 1->4->2->3.

示例 2:

  1. 给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.

2. 实现思路

这个题目可以使用快慢指针来实现,具体实现思路如下:

  • 首先使用快慢两个指针,获取链表的中点
  • 从链表的中点断开,慢指针指向前半个链表,快指针指向后半个链表
  • 将后半个链表进行翻转,让快指针重新指向翻转后的后半个链表
  • 按照题目要求的规则将两个链表的节点添加在一起

    3. 代码实现

    1. /**
    2. * Definition for singly-linked list.
    3. * function ListNode(val, next) {
    4. * this.val = (val===undefined ? 0 : val)
    5. * this.next = (next===undefined ? null : next)
    6. * }
    7. */
    8. /**
    9. * @param {ListNode} head
    10. * @return {void} Do not return anything, modify head in-place instead.
    11. */
    12. var reorderList = function(head) {
    13. if(!head || !head.next) return
    14. let slow = head
    15. let fast = head
    16. // 获取链表的中间节点
    17. while(fast && fast.next){
    18. slow = slow.next
    19. fast = fast.next.next ? fast.next.next : null
    20. }
    21. // 将链表从中点断开,fast指向后半个链表,slow指向前半个链表
    22. fast = slow.next
    23. slow.next = null
    24. slow = head
    25. // 反转链表后半部分
    26. let pre = null
    27. let cur = fast
    28. while(cur){
    29. let temp = cur.next
    30. cur.next = pre
    31. pre = cur
    32. cur = temp
    33. }
    34. // 将fast指向后半段反转后的链表
    35. fast = pre
    36. // 将两个链表按照要求进行合并
    37. while(fast){
    38. let slowNext = slow.next
    39. let fastNext = fast.next
    40. slow.next = fast
    41. fast.next = slowNext
    42. slow = slowNext
    43. fast = fastNext
    44. }
    45. };

    4. 提交结果

    143. 重排链表 - 图1