148. 排序链表

65 阅读1分钟

题目描述

leetcode-cn.com/problems/so…

分析

利用归并排序来完成链表的排序

在归并过程中,断开链表,然后在合并新链表

算法

归并排序

过程

首先计算链表的总长度,在每次断开链表的时候,都是从中间断开,然后排序后再把两端接上

断开链表,分别进行排序

合并过程中,注意要挪动指针

算法

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var sortList = function (head) {
  if (!head || !head.next) return head
  let n = 0
  let cur = head
  while (cur) {
    cur = cur.next
    n++
  }

  return mergeSort(head, n)
}

function mergeSort(head, n) {
  if (n <= 1) return head

  const mid = n >> 1,
    ret = new ListNode()
  let p = ret,
    p1 = head,
    p2 = head

  for (let i = 1; i < mid; i++) {
    p2 = p2.next
  }
  const tmp = p2.next
  p2.next = null
  p2 = tmp

  let l1 = mergeSort(head, mid)
  let l2 = mergeSort(p2, n - mid)

  while (l1 || l2) {
    if (!l2 || (l1 && l1.val <= l2.val)) {
      p.next = l1
      l1 = l1.next
    } else {
      p.next = l2
      l2 = l2.next
    }
    p = p.next
  }

  return ret.next
}