LeetCode -- Merge K Sorted Lists

Question:

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

 

Analysis:

合并k个排好序的链表,返回最终一个总的排序列表。分析并描述他的复杂度。limited

思路一:我的思路是,设置一个头结点,然后申请一个数组,记录该位置的这组链表是否全部放入新的链表中。不再使用额外的空间,直接用原来的节点。测试了所有情况,都通过了,不过好可惜,time limit exceeded..可能因为我的方法,遍历n次,每次从里面选出最小的一个,所以导致时间复杂度为O(n2).

代码:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    private ListNode tail;
    
    
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length == 0)
            return null;
        if(lists.length == 1)
            return lists[0];
        
        int l = 0;
        for(int i=0; i<lists.length; i++) {
            if(lists[i] == null)
                l++;
        }
        if(l == lists.length)
            return null;
        
       boolean[] mark = new boolean[lists.length]; //初始化时false
        
        ListNode h = new ListNode(-1);
        tail = h;
        int flag = 0;
        
        while(flag < lists.length) {
            int min = Integer.MAX_VALUE;
            int mint = -1;
            for(int i=0; i<lists.length; i++) {
                if(lists[i] == null)
                    continue;
                if(lists[i].val < min && mark[i] == false && lists[i] != null) {
                    min = lists[i].val;
                    mint = i;
                }
            }
            if(mint == -1)
                return h.next;
            //找到了本轮循环的最小值
            tail.next = lists[mint];
            if(lists[mint].next != null) {
                tail = lists[mint];
                lists[mint] = lists[mint].next;
                tail.next = null;
            } else {
                mark[mint] = true;
                tail = lists[mint];
                flag++;
            }
            
        }
        return h.next;
    }
}

思路二:使用归并排序(Merge Sort)算法。是一个比较经典的O(nlogn)的排序算法。思路是先分成两个子任务,然后递归求子任务,最后回溯回来。这个题目也是这样,先把k个list分成两半,然后继续划分,知道剩下两个list就合并起来,合并时会用到Merge Two Sorted Lists这道题.

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
        //用归并排序的方法
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length == 0)
            return null;
        if(lists.length == 1)
            return lists[0];
        
        int l = 0;
        for(int i=0; i<lists.length; i++) {
            if(lists[i] == null)
                l++;
        }
        if(l == lists.length)
            return null;
        
        return deal(lists, 0, lists.length - 1);         
    }
    
    
    private ListNode deal(ListNode[] lists, int i, int j) { //重点!!掌握这种思路
        // TODO Auto-generated method stub
        if(i < j) {
            int m = (i + j) / 2;
            return mergeTwoLists(deal(lists, i, m), deal(lists, m+1, j)); 
        }
        return lists[i];
    }

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode p1 = l1;
        ListNode p2 = l2;
        
        if(l1 == null && l2 == null)
            return null;
        if(l1 == null && l2 != null)
            return l2;
        if(l1 != null && l2 == null)
            return l1;
        
        ListNode fakeHead = new ListNode(0);
        ListNode p = fakeHead;
        
        while (p1 != null && p2 != null){
            if (p1.val <= p2.val) {
                p.next = p1;
                p1 = p1.next;
                p = p.next;
            } else {
                p.next = p2;
                p2 = p2.next;
                p = p.next;
            }
        }
        
        if(p1 != null)
            p.next = p1;
        if(p2 != null)
            p.next = p2;
        return fakeHead.next;
    }
}

总结:遇到这种把n个排好序的东西混合成一个时,要立马想到归并排序。递归+回溯的方法!!

posted @ 2015-09-12 20:16  江湖小妞  阅读(154)  评论(0编辑  收藏  举报