LeetCode[148]Sort List 解法及代码

题目描述:

Sort a linked list in O(n log n) time using constant space complexity.

Example 1:

Input: 4->2->1->3
Output: 1->2->3->4
Example 2:

Input: -1->5->3->4->0
Output: -1->0->3->4->5

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解法

题目要求算法复杂度是O(nlogn),故不能使用冒泡和插入排序,因为是链表不能随机寻址,所以只能使用归并排序。

链表有两个基本操作需要先实现,拆分(split)和合并(merge), 用这两个基本操作就可实现算法。

拆分(split): 给一个head和n, 拆成n个元素的左链表,剩下为右链表,返回右链表
如:1->2->3, 1; 返回2->3;

合并(merge): 给两个链表,按从小到大的顺序合并成一个链表,并返回
如:1->3, 2->4; 1->2->3->4;

则题目所给4->2->1->3, 先拆成4,2,1,3, 然后归并2->4, 1->3, 1->2->3->4

因为题目又要求只能用常量空间,所以不能开额外的容器存拆出来的元素,对编码技巧有一定要求。

代码

  ListNode* merge(ListNode* l1, ListNode* l2) {
    ListNode dummyHead(0);
    ListNode* p = &dummyHead;
    while (l1 && l2) {
      if (l1->val < l2->val) {
        p->next = l1;
        l1 = l1->next;
      } else {
        p->next = l2;
        l2 = l2->next;
      }
      p = p->next;
    }
    p->next = l1 ? l1 : l2;

    return dummyHead.next;
  }

  ListNode* split(ListNode* head, int n) {
    ListNode dummyNode(0);
    auto p = &dummyNode;
    int len = 0;
    auto pre = head;
    while(head && len <= n) {
      if (len == n) { p->next = head;
        pre->next = NULL;
        break;
      }
      pre = head;
      head = head->next;
      len++;
    }
    return dummyNode.next;
  }

  ListNode* sortList(ListNode* head) {
    int len = 0;
    ListNode* p = head;
    while(p) {
      p = p->next;
      len++;
    }

    ListNode dummyHead(0);
    dummyHead.next = head;
    for(int size = 1; size <= len; size <<= 1) {
      auto cur = dummyHead.next;
      auto tail = &dummyHead;
      while (cur) {
        auto left = cur;
        auto right = split(left, size);
        cur = split(right, size);
        tail->next = merge(left, right);
        while(tail->next) tail = tail->next;
      }
    }
    return dummyHead.next;
  }

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注