单链表的归并排序

本文探讨了在链表排序问题中,如何利用归并排序算法达到O(nlogn)的时间复杂度和常数空间复杂度。通过详细解析归并排序的基本思想、中间节点查找方法以及链表合并过程,确保算法效率与正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本题目来源于LeetCode,具体如下:

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

题目要求复杂度O(nlogn),因此我们很自然考虑使用快速排序或者归并排序,但是后来经过实践证明,使用快速排序总是AC超时,归并排序则可以正确AC。

分析一下原因,个人认为是与测试数据有关,因为快速排序不能保证算法复杂度一定是O(nlogn),当数据比较集中时,即使做随机选取key值,算法的复杂度也非常接近O(N^2),因此会出现超时,所以考虑使用归并排序。

下面是采用归并排序的思路已经AC代码:

主要考察3个知识点,
知识点1:归并排序的整体思想
知识点2:找到一个链表的中间节点的方法
知识点3:合并两个已排好序的链表为一个新的有序链表

归并排序的基本思想是:找到链表的middle节点,然后递归对前半部分和后半部分分别进行归并排序,最后对两个以排好序的链表进行Merge。

public class CzyList {
	/**
	 * Definition for singly-linked list.
	 * public class ListNode {
	 *     int val;
	 *     ListNode next;
	 *     ListNode(int x) { val = x; }
	 * }
	 */
	    public static ListNode sortList(ListNode head) {
	        if (head == null || head.next == null)
	            return head;
	        ListNode f = head.next.next;
	        ListNode p = head;
	        while (f != null && f.next != null) {
	            p = p.next;
	            f =  f.next.next;
	        }
	        
	        ListNode temp=p.next;
	        p.next=null;
	        ListNode h1=sortList(head);
	        //p.next=null;
	        ListNode h2 = sortList(temp);
	        //p.next = null;//保证每次分半之后  前半都有一个结尾标志null;;;;;;
	        
	        return merge(h1, h2);
	    }
	    public static ListNode merge(ListNode h1, ListNode h2) {
	        ListNode hn = new ListNode(Integer.MIN_VALUE);
	        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 = h1;
	        if (h2 != null)
	            c.next = h2;
	        return hn.next;
	    }
	
	public static void main(String[] args){
		ListNode head=new ListNode(6);
		head.next=new ListNode(3);
		head.next.next=new ListNode(5);
		head.next.next.next=new ListNode(4);
		head=sortList(head);
		while(head!=null){
			System.out.println(head.val);
			head=head.next;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值