码迷,mamicode.com
首页 > 编程语言 > 详细

LeetCode-Sort List,链表排序(插入和归并),时间复杂度O(n^2) and O(nlgn)

时间:2015-02-28 21:46:36      阅读:288      评论:0      收藏:0      [点我收藏+]

标签:

题目:

1、Sort a linked list using insertion sort

2、Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.

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

LeetCode上的三道题,汇总在一块。自认为这三道题有层层递进的关系。

1、首先第一个,按插入法进行排序,比较简单,但是不同于数组的插入排序,为什么?因为链表的插入需要O(1),而数组需要O(n)。

代码如下:

public ListNode insertionSortList(ListNode head) {
        ListNode newHead = new ListNode(0);
        ListNode pNode = head;
        while (pNode != null) {
        	ListNode node = newHead;
        	while (node.next != null) {
        		if (node.next.val > pNode.val)
        			break;
        		node = node.next;
        	}
        	ListNode temp = pNode.next;
        	pNode.next = node.next;
        	node.next = pNode;
        	pNode = temp;
        }
    	return newHead.next;
    }
在代码第一行中加入了一个头节点,这样更有利于插入操作的统一性,不用另外考虑头节点。接下来就是遍历整个链表,找到合适的位置,进行插入!

2、第二个的问题也比较简单,可以参看数组的归并,代码如下:

private ListNode mergeTwoLists(ListNode head1, ListNode head2) {
    	ListNode head = new ListNode(0);
    	ListNode root = head;
    	while (head1 != null && head2 != null) {
    		if (head1.val < head2.val) {
    			head.next = head1;
    			head1 = head1.next;
    		} else {
    			head.next = head2;
    			head2 = head2.next;
    		}
    		head = head.next;
    	}
    	if (head1 != null) {
    		head.next = head1;
    	}
    	if (head2 != null) {
    		head.next = head2;
    	}
    	return root.next;
    }
3、有了上面两个题做基础,第三个就非常好解答了。首先用插入排序肯定不行,因为他的时间复杂度是O(n^2)。联系到第二道题,就可以联想到归并排序,对,就是这个思路:

代码如下:

public ListNode sortList(ListNode head) {
    	if (head == null) {
    		return head;
    	}
    	int len = 0;
    	ListNode node = head;
        while (node != null) {
        	len++;
        	node = node.next;
        }
        if (len == 1) {
        	return head;
        }
        node = head; 
        for (int i = 0; i < (len/2)-1; i++) {
        	node = node.next;
        }
        ListNode midNode = node.next;
        node.next = null;
        head = sortList(head);
        midNode = sortList(midNode);
        return mergeTwoLists(head, midNode);
    }
    private ListNode mergeTwoLists(ListNode head1, ListNode head2) {
    	ListNode head = new ListNode(0);
    	ListNode root = head;
    	while (head1 != null && head2 != null) {
    		if (head1.val < head2.val) {
    			head.next = head1;
    			head1 = head1.next;
    		} else {
    			head.next = head2;
    			head2 = head2.next;
    		}
    		head = head.next;
    	}
    	if (head1 != null) {
    		head.next = head1;
    	}
    	if (head2 != null) {
    		head.next = head2;
    	}
    	return root.next;
    }
完全是归并排序的模式,但是对于上面取中间节点比较繁琐,有另外一个办法,只需要遍历一次链表:两个指针p1,p2同时从head开始,p1每次next一次,即p1 = p1.next;但是p2每次next两次,即p2 = p2.next.next;

显然,当p2到达未端时,就可以认为p1指向的是中间节点!!!









LeetCode-Sort List,链表排序(插入和归并),时间复杂度O(n^2) and O(nlgn)

标签:

原文地址:http://blog.csdn.net/my_jobs/article/details/43988745

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!