现在的位置: 首页 > 综合 > 正文

[LeetCode] Sort List

2014年02月23日 ⁄ 综合 ⁄ 共 1460字 ⁄ 字号 评论关闭

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

这题思路比较直接。按照题目要求,需要在O(N*logN)时间内完成排序,所以可以考虑的排序方法只有三个:快速排序、归并排序和堆排序。然而,快速排序要求能在常数时间内置换两个指定元素,所以需要支持O(1)时间内的随机访问,这个无法在链表上实现,所以可以排除快速排序。此外,堆排序需要O(N)的额外空间进行堆的建立,而题目要求常数的空间复杂度,所以也可以排除。如此一来,只有归并排序可以考虑了。

按照分治法原理,其实也就只用实现两个步骤,即拆分链表和合并链表,都可以通过链表实现。把一个链表拆分成两半,简单做法就是先扫描一遍获得链表长度,然后再扫描一半长度进行拆分。这样需要两次扫描,虽然时间复杂度一样。更有效的方法是使用2个快慢指针,当快指针走到头的时候,慢指针会到达第一个的子链表的尾部。合并链表很直接,因为无论是用数组还是链表,都只用顺序扫描两个序列。

	// merge the two sorted sublists
	private ListNode merge(ListNode head1, ListNode head2) {
		if (head1 == null) {
			return head2;
		} else if (head2 == null) {
			return head1;
		}

		ListNode head, prev;
		if (head1.val < head2.val) {
			head = head1;
			head1 = head1.next;
		} else {
			head = head2;
			head2 = head2.next;
		}
		prev = head;

		while (head1 != null && head2 != null) {
			if (head1.val < head2.val) {
				prev.next = head1;
				head1 = head1.next;
			} else {
				prev.next = head2;
				head2 = head2.next;
			}
			prev = prev.next;
		}

		if (head1 != null) {
			prev.next = head1;
		} else if (head2 != null) {
			prev.next = head2;
		}

		return head;
	}

	public ListNode sortList(ListNode head) {
		ListNode head1, head2; // sublist heads

		// split the list into two sublists
		if (head == null || head.next == null) {
			return head;
		} else {
			ListNode fastNode = head.next, slowNode = head;
			while (fastNode != null) {
				fastNode = fastNode.next;
				if (fastNode != null) {
					fastNode = fastNode.next;
					slowNode = slowNode.next;
				}
			}

			head1 = head;
			head2 = slowNode.next;
			slowNode.next = null;
		}

		// sort the two sublists recursively
		head1 = sortList(head1);
		head2 = sortList(head2);

		return merge(head1, head2);
	}

其实我本来想把拆分链表这一步也用一个函数封装的,不过这样的话要求对两个子链表的表头地址传引用,在Java里不好实现,不过可以在C++代码里引入二级指针或者对节点地址传引用实现。

抱歉!评论已关闭.