Sort List排序链表

在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

示例 1:

输入: 4->2->1->3
输出: 1->2->3->4

示例 2:

输入: -1->5->3->4->0
输出: -1->0->3->4->5

这道题要求对链表排序且对时间和空间复杂度有要求,主要用归并排序的思想。每次把链表一分为二(快慢指针法),然后对两个分链表进行合并,这里在discuss部分看到一个很精简也很容易理解的代码,用了双重递归,具体分析过程不做解释,对递归的调用再强调一遍要注意边界条件和细节处理。由快慢指针分割后,原链表根据长度不同会出现以下情况:

原链表:

1:nullptr或者长度为1,直接return

2:长度为2:

3:长度为3:

当长度为3时,又被分为长度为1和长度为2的子情况,所以只有情况1和情况2。

为什么要讨论边界情况,因为merge函数对传入的两个链表进行合并,就需要知道在分割的最底层情况两个子链表l1和l2会出现什么情况,我们在merge函数的合并函数以及开始的非空判断返回时才能考虑周全,不会遗漏情况。

下面是c++代码(时间复杂度O(nlogn),空间复杂度O(n)由于归并排序必须要辅助空间为n的数组):

  ListNode* merge(ListNode* l1, ListNode* l2) {
	  if (!l1 && l2) {
		  return l2;
	  }
	  if (l1 && !l2) {
		  return l1;
	  }
	  if (l1 == l2) {
		  return l1;
	  }
	  if (l1->val < l2->val) {
		  l1->next = merge(l1->next,l2);
		  return l1;
	  }
	  else {
		  l2->next = merge(l1, l2->next);
		  return l2;
	  }
  }
  ListNode* sortList(ListNode* head) {
	  if (!head || !head->next) {
		  return head;
	  }
	  ListNode* slow = head;
	  ListNode* fast = head;
	  ListNode* pre = head;
	  while (fast && fast->next) {
		  pre = slow;
		  slow = slow->next;
		  fast = fast->next->next;
	  }
	  pre->next = nullptr;
	  return merge(sortList(head), sortList(slow));
  }





猜你喜欢

转载自blog.csdn.net/qq_26410101/article/details/80443720