LeetCode Sort List

题目:

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

题意:

用O(nlogn)的时间复杂度和一个O(1)的空间复杂度来对一个单链表进行排序。

题解:

因为对时间复杂度和空间复杂度都有要求,对照了各种排序算法,发现只有归并排序才能满足题目的要求。所以考虑用归并排序来做。首先就要了解什么是归并排序。归并排序中最常用的就是二路归并,也就是两两归并,我们采用分别找到中间节点,然后就是归并操作了。其中归并排序分别有对数组和单链表的操作,首先我们可以看到对这两个数据结构进行操作,因为此题是单链表,而单链表由于只能顺序地访问,所以我们不能采用其他的堆排序和快排,会非常麻烦,所以只能用归并排序比较好;另外,归并排序的要点在于递归地访问中间节点,这也是归并排序的重点。下面分别写了对于单链表和数组的归并排序算法:

public ListNode sortList(ListNode head)
{
		if(head == null || head.next == null)
			return head;
        ListNode p = head;
        ListNode f = head.next.next;
        if(f != null) //首先用两个指针,其中第二个指针比第一个指针每一步快走两步,那么这样第二个指针走到末尾,第一个指针就指到中间节点
        {
            while(f.next != null && f.next.next != null)
            {
            	p = p.next;
            	f= f.next.next;
            }
        }
        ListNode h2 = sortList(p.next);       //对左边的单链表进行归并
        p.next = null;
        return merge(sortList(head),h2);      //合并两个单链表
	}
	public ListNode merge(ListNode h1,ListNode h2)        //合并单链表
	{
		ListNode hn = new ListNode(-1);
		ListNode c = hn;
		while(h1 != null && h2 != null)
		{
			if(h1.val <= h2.val)
			{
				c.next = h1;
				h1 = h1.next;
			}
			else
			{
				c.next = h2;
				h2 = h2.next;
			}
			c = c.next;
		}
		if(h1 == null)
			c.next = h2;
		else
			c.next = h1;
		return hn.next;
}

下面是对数组的归并排序:

public void sort(int[] data,int left,int right)
	{
		if(left >= right)
			return;
		int center = (left + right) / 2;         //数组只要有下标就行了
		sort(data,left,center);      //递归
		sort(data,center+1,right);   //递归
		merge(data,left,center,right);   //合并
	}
	public void merge(int[] data,int left,int center,int right)          //合并
	{
		int[] tmpArr = new int[data.length];
		int mid = center + 1;
		int third = left;
		int tmp = left;
		while(left <= center && mid <= right)
		{
			if(data[left] <= data[mid])
				tmpArr[third++] = data[left++];
			else
				tmpArr[third++] = data[mid++];
		}
		while(mid <= right)
		{
			tmpArr[third++] = data[mid++];
		}
		while(left <= center)
			tmpArr[third++] = data[left++];
		while(tmp <= right)
			data[tmp] = tmpArr[tmp++];
	}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值