LeetCode 148: Sort List (链表排序)

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

 

分析:

题目要求对链表进行排序,如果采用插入、冒泡等排序方式,则时间复杂度将是O(n*n),达不到题目要求的O(n log n)的要求。O(n log n)复杂度的有快排和归并排序,对于链表来说,归并排序更适合一点。这样题目转换为将一个链表拆分成两个有序的链表,然后再进行归并排序。关键就在于链表中点的获取。对于链表中点获取可以采取快慢指针法,快指针每次进2步,慢指针每次一步,这样快指针到达终点时,慢指针将处于链表中点处。

代码如下,执行时间约 68ms:

 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
		ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
			ListNode* head =NULL, *tmp;
			while (l1 && l2)
			{
				if (l1->val <= l2->val)
				{
					if (!head)
					{
						head = l1;
						tmp = head;
					}else{
						tmp ->next= l1;
						tmp = tmp->next;
					}
					l1 = l1->next;
				}else{
					if (!head)
					{
						head = l2;
						tmp = head;
					} 
					else
					{
						tmp ->next = l2;
						tmp = tmp->next;
					}
					l2 = l2->next;
				}
			}
			if (l1)
			{
				tmp->next = l1;
			}
			if (l2)
			{
				tmp->next = l2;
			}
			return head;
		}
    ListNode *sortList(ListNode *head) {
        ListNode tmpNode = ListNode(INT_MIN);
		if (head==NULL || head->next==NULL)
			{
				return head;
			}
			ListNode *p1=head, *p2=head->next;
			while (p2 && p2->next)
			{
				p1 = p1->next;
				p2 =p2->next->next;
			}
			p2 = p1->next;
			p1->next= NULL;
			return mergeTwoLists(sortList(head), sortList(p2));
    }
};

2018-11-12:补充

上述方法虽满足了O(nlogn)的时间和O(1)的空间复杂度,但通过快慢指针方法找链表中点,需要首先遍历链表,浪费了很多操作。下面这种方法也是归并排序,但不需要扫描链表获得链表中点、也不递归。在实现上比之前的快很多。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

static struct ListNode *merge(struct ListNode*a, struct ListNode*b) {

	struct ListNode head, *tail;
	tail = &head;
	while (a && b) {
		if ((a->val <= b->val) ) {
			tail->next = a;
			a = a->next;
		} else {
			tail->next = b;
			b = b->next;
		}
		tail = tail->next;
	}
	tail->next = a ? : b;
	return head.next;
}
#define MAX_LIST_LENGTH_BITS 31

struct ListNode* sortList(struct ListNode* head) {
    struct ListNode *part[MAX_LIST_LENGTH_BITS + 1];
	int lev;
	int max_lev = 0;
	struct ListNode *bnode;

	if (head == NULL || head->next==NULL)
		return head;
	memset(part, 0, sizeof(part));
	bnode = head;

	while (bnode) {
		struct ListNode *cur = bnode;
		bnode = bnode->next;
		cur->next = NULL;

		for (lev = 0; part[lev]; lev++) {
			cur = merge(part[lev], cur);
			part[lev] = NULL;
		}
		if (lev > max_lev) {
			if ((lev >= MAX_LIST_LENGTH_BITS)) {
				lev--;
			}
			max_lev = lev;
		}
		part[lev] = cur;
	}

	for (lev = 0; lev < max_lev; lev++)
		if (part[lev])
			bnode = merge(part[lev], bnode);

	bnode = merge(part[max_lev], bnode);

	return bnode;
}

与之类似的还有

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* sortList(struct ListNode* head) {
	struct ListNode *p, *q, *e, **tail;
	int k, psize, qsize;


	if (!head)
		return 0;
	int count = 0;
	struct ListNode *pHead = head;
	p = pHead;
	while (p) {
		count++;
		p = p->next;
	}
	for (k = 1; k < count; k *= 2) {
		tail = &pHead;
		for (p = q = pHead; p; p = q) {
			/* step 'k' places from p; */
			for (psize = 0; q && psize < k; psize++)
				q = q->next;
			qsize = k;

			/* two lists, merge them. */
			while (psize || (qsize && q)) {
				/* merge the next element */
				if (psize == 0 || ((qsize && q) && ((p->val - q->val) >= 0))) {
					/* p is empty, or p > q, so q next */
					e = q;
					q = q->next;
					qsize--;
				} else {
					e = p;
					p = p->next;
					psize--;
				}
				e->next = NULL; /* break accidental loops. */
				*tail = e;
				tail = &e->next;
			}
		}
	}
	return pHead;
}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值