leetcode题目解答---- SortList

题目:

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

这题还是比较纠结的,因为对于时间复杂度和空间复杂度都是有要求的。

时间复杂度是O(n log n)只能使用快速排序和归并排序。

空间复杂度是O(1)又必须是常数空间量。

对于快速排序,复习一下:

其思路是

1)用第一个数将当前数组/链表分为两部分,一部分小于这个数,另一部分大于这个数。

2)对小于这部分进行递归处理,步骤同1)。

3)对大于这部分进行递归处理,步骤同1)。

4)完毕。

对于归并排序,复习一下:

其思路是:

1)将数组/链表从中间截断,分为左右两部分。

2)递归中间截断两部分。

3)对小部分进行排序

4)合并每一个小部分。

本题,我从这三部分都进行了代码实现,对他们的时间进行了验证。

冒泡排序:其时间复杂度为O(n^2),在长度比较小时,满足要求,超过一定长度无法满足。

其空间复杂度为O(1);

快速排序,在本题链表中,其时间复杂度为n/2+O(n^2),(注:在数组中,其时间复杂度为O(n log n)~O(n^2),可能是本题没设计好。)相比冒泡排序,其复杂度是一样的。

其空间复杂度为O(log n)的递归调用,如果算上栈变量,比如左右指针这些,值为更大。

归并排序:本题链表,能解决此问题的就是归并排序了。

其时间复杂度:nlog(n) + n/2 log(n),因此其复杂度为O(n log n)满足要求。

空间复杂度:有两个递归调用,因此,空间复杂度为2*O(log n),也就是O (log n)。


具体代码思路:

冒泡排序:

1)两个循环,每两个值,进行值替换。也可以修改链表指针指向。两者难度相当,但在本题中,时间复杂度不满足要求。

快速排序:

1)遍历链表,将链表分为两个,一个小于第一个值,一个大于等于第一个值。

2)递归第一步。

3)将两个分开链表合并。

本题时间复杂度不满足要求,但是若是数组就可能满足了,因为数组可以双向遍历。所以最好的情况是分割点总是落在中间,这就满足情况,最坏的情况,一边只有一个,这时其时间复杂度相当于冒泡排序。


归并排序:

1)间隔遍历链表,找到中间点。(数组时不需要这步)。

2)递归处理隔断两部分。

3)将这两部分进行归并。

能确保隔断点总是在中间位置,所以时间复杂度是慢去要求的。其空间复杂度不太满足要求,不是一个常数复杂度。但本题已经被系统AC了。

代码见下,很多不必要的代码,但是都是知识点,供sherry多接触些排序算法:


// Definition for singly-linked list.
 struct ListNode {
     int val;
     ListNode *next;
     ListNode(int x) : val(x), next(NULL) {}
 };
 
class Solution {
public:
    ListNode *sortList(ListNode *head) 
	{
		if (head == NULL)
		{
			return NULL;
		}
		if (head->next == NULL)
		{
			return head;
		}
		ListNode* r_head = head;
		ListNode* head1 = head;
		ListNode* head2 = head;
		ListNode* end;
		int count = 0;
		while (head2->next && head2->next->next)
		{
			head1 = head1->next;
			head2 = head2->next->next;
			count++;
		}
		if (head2->next == NULL)
		{
			end = head2;
		}
		else if (head2->next->next == NULL)
		{
			end = head2->next;
		}
		if (count < 0)
		{
			bubblesort(head);
			return head;
		}
		else if (count < 0)
		{
			qucksort(head,end);
			return head;
		}
		else
		{
			head2 = head1->next;
			head1->next = NULL;
			head1 = head;
			head = MergeList(MergeSort(head1),MergeSort(head2));
			return head;
		}
    }
	
private:
	ListNode* MergeSort(ListNode* head)
	{
		if (head == NULL)
		{
			return NULL;
		}
		else if (head->next == NULL)
		{
			return head;
		}
		ListNode* r_head = head;
		ListNode* head1 = head;
		ListNode* head2 = head;
		while (head2->next && head->next->next)
		{
			head1 = head1->next;
			head2 = head2->next->next;
		}
		head2 = head1->next;
		head1->next = NULL;
		head1 = head;
		r_head = MergeList(MergeSort(head1),MergeSort(head2));
		return r_head;		
	}
	ListNode* MergeList(ListNode* prehead,ListNode* nexthead)
	{
#if 0


		ListNode* newtmp = new ListNode(0);
		ListNode *tmp = newtmp;
		if (prehead == NULL)
		{
			return nexthead;
		}
		if (nexthead == NULL)
		{
			return prehead;
		}
		while (prehead&&nexthead)
		{
			if (prehead->val < nexthead->val)
			{
				tmp->next= prehead;
				prehead = prehead->next;
			}
			else
			{
				tmp->next = nexthead;
				nexthead = nexthead->next;
			}
			tmp = tmp->next;
		}
		tmp->next = (prehead!=NULL?prehead:nexthead);
		tmp = newtmp->next;
		delete newtmp;
		return tmp;	
#endif
#if 1
		ListNode *tmp;
		if (prehead == NULL)
		{
			return nexthead;
		}
		if (nexthead == NULL)
		{
			return prehead;
		}
		if (prehead->val < nexthead->val)
		{
			tmp = prehead;
			prehead = prehead->next;
		}
		else
		{
			tmp = nexthead;
			nexthead = nexthead->next;
		}
		tmp = tmp->next;
		tmp = MergeList(prehead,nexthead);
		return tmp;
#endif
		
	}
	void bubblesort(ListNode* head)
	{
		ListNode* p = head;
		while (p)
		{
			ListNode *pre = p->next;
			while (pre)
			{
				if (pre->val < p->val)
				{
					int temp = p->val;
					p->val = pre->val;
					pre->val = temp;
				}
				pre = pre->next;
			}
			p = p->next;		
		}
		
	}
	void qucksort(ListNode* head,ListNode* end)
	{
		if (head == NULL)
		{
			return;
		}
		ListNode * head1,*end1,*head2,*end2;
		head1 = end1 = head2 = end2 = NULL;
		ListNode* pre1,*pre2,*p;
		pre1 = pre2 = p = NULL;
		int key = head->val;
		p = head->next;
		head->next = NULL;
		while (p != NULL)
		{
			if (p->val < key)
			{
				if (!head1)
				{
					head1 = p;
					pre1 = p;
					pre1->next = NULL;
				}
				else
				{
					pre1->next = p;
					pre1 = pre1->next;
					pre1->next = NULL;
				}
				
			}
			else
			{
				if (!head2)
				{
					head2 = p;
					pre2 = p;
					pre2->next = NULL;
				}
				else
				{
					pre2->next = p;
					pre2 = pre2->next;
					pre2->next = NULL;
				}
			}
		}
		end1 = pre1;
		end2 = pre2;
		qucksort(head1,end1);
		qucksort(head2,end2);
		if (end1&&head2)
		{
			end1->next = head;
			head->next = head2;
			head = head1;
			end = end2;
		}
		else if (end1)
		{
			end1->next = head;
			end = head;
			head = head1;
		}
		else if (end2)
		{
			head->next = head2;
			end = end2;
		}							
	}
		
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值