在O(N lgK) 时间内合并K个有序链表

问题:

在O(N lgK) 时间内合并K个有序链表, 这里N指的是K个链表中所有的元素个数。

分析:

这是一道非常经典的面试题,在很多大公司的面试题中,此题频繁出现。这题也是算法导论的作业题。

这题的思路如下:

1) 在每一个链表中取出第一个值,然后把它们放在一个大小为K的数组里,然后把这个数组当成heap,然后把该堆建成最小堆。此步骤的时间复杂度为O(K)

2 )取出堆中的最小值(也是数组的第一个值),然后把该最小值所处的链表的下一个值放在数组的第一个位置。如果链表中有一个已经为空(元素已经都被取出),则改变heap的大小。然后,执行MIN-HEAPIFY操作,此步骤的时间复杂度为O(lg K).

3 ) 不断的重复步骤二,直到所有的链表都为空。

代码如下:

  1. class ListNode {  
  2.     int val;  
  3.     ListNode next;  
  4.     ListNode(int x) {  
  5.         val = x;  
  6.         next = null;  
  7.     }  
  8. }  
  9.     
  10. public class Solution {  
  11.     public static void main(String[] args) {  
  12.               
  13.         ListNode n1 = new ListNode(1);  
  14.         ListNode n7 = new ListNode(2);  
  15.         ListNode n9 = new ListNode(2);  
  16.         ListNode n2 = new ListNode(1);  
  17.         ListNode n4 = new ListNode(1);  
  18.         ListNode n8 = new ListNode(2);  
  19.       
  20.         ArrayList<ListNode> lists = new ArrayList<ListNode>();    
  21.         n1.next = n7;  
  22.         n7.next = n9;  
  23.         n2.next = n4;  
  24.         n4.next = n8;  
  25.           
  26.         lists.add(n1);  
  27.         lists.add(n2);  
  28.           
  29.         Solution test = new Solution();  
  30.         ListNode head = test.mergeKLists(lists);  
  31.         while(head != null) {  
  32.             System.out.println(head.val);  
  33.             head = head.next;  
  34.         }  
  35.     }  
  36.       
  37.     public ListNode mergeKLists(ArrayList<ListNode> lists) {  
  38.         ArrayList<ListNode> heap = new ArrayList<ListNode>();  
  39.         for (int i = 0; i < lists.size(); i++) {  
  40.             if (lists.get(i) != null) {  
  41.                 heap.add(lists.get(i));  
  42.             }  
  43.         }  
  44.           
  45.         ListNode head = null;  
  46.         ListNode current = null;  
  47.         if (heap.size() == 0return null;  
  48.         minHeapify(heap);  
  49.         while (heap.size() != 0) {  
  50.             if (head == null) {  
  51.                 head = heap.get(0);  
  52.                 current = heap.get(0);  
  53.             } else {  
  54.                 current.next = heap.get(0);  
  55.                 current = current.next;  
  56.             }  
  57.               
  58.             if (current.next != null) {  
  59.                 heap.set(0, current.next);  
  60.                 heapify(heap, 0);  
  61.             } else {  
  62.                 heap.remove(0);  
  63.                 minHeapify(heap);  
  64.             }  
  65.         }  
  66.         return head;  
  67.     }  
  68.       
  69.     public void heapify(ArrayList<ListNode> heap, int index) {  
  70.         int position = index;  
  71.         int left = 2 * index + 1;  
  72.         int right = 2 * index + 2;   
  73.           
  74.         if(left < heap.size() && heap.get(left).val < heap.get(position).val) {  
  75.             position = left;  
  76.         }  
  77.           
  78.         if(right < heap.size() && heap.get(right).val < heap.get(position).val) {  
  79.             position = right;  
  80.         }  
  81.           
  82.         if (position != index) {  
  83.             ListNode temp = heap.get(position);  
  84.             heap.set(position, heap.get(index));  
  85.             heap.set(index, temp);  
  86.             heapify(heap, position);  
  87.         }  
  88.     }  
  89.       
  90.     public void minHeapify(ArrayList<ListNode> heap) {  
  91.         for (int i = heap.size()/2 - 1; i >= 0; i–) {  
  92.             heapify(heap, i);  
  93.         }  
  94.     }  
  95. }  
class ListNode {
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
        next = null;
    }
}

public class Solution {
    public static void main(String[] args) {

        ListNode n1 = new ListNode(1);
        ListNode n7 = new ListNode(2);
        ListNode n9 = new ListNode(2);
        ListNode n2 = new ListNode(1);
        ListNode n4 = new ListNode(1);
        ListNode n8 = new ListNode(2);

        ArrayList<ListNode> lists = new ArrayList<ListNode>();  
        n1.next = n7;
        n7.next = n9;
        n2.next = n4;
        n4.next = n8;

        lists.add(n1);
        lists.add(n2);

        Solution test = new Solution();
        ListNode head = test.mergeKLists(lists);
        while(head != null) {
            System.out.println(head.val);
            head = head.next;
        }
    }

    public ListNode mergeKLists(ArrayList<ListNode> lists) {
        ArrayList<ListNode> heap = new ArrayList<ListNode>();
        for (int i = 0; i < lists.size(); i++) {
            if (lists.get(i) != null) {
                heap.add(lists.get(i));
            }
        }

        ListNode head = null;
        ListNode current = null;
        if (heap.size() == 0) return null;
        minHeapify(heap);
        while (heap.size() != 0) {
            if (head == null) {
                head = heap.get(0);
                current = heap.get(0);
            } else {
                current.next = heap.get(0);
                current = current.next;
            }

            if (current.next != null) {
                heap.set(0, current.next);
                heapify(heap, 0);
            } else {
                heap.remove(0);
                minHeapify(heap);
            }
        }
        return head;
    }

    public void heapify(ArrayList<ListNode> heap, int index) {
        int position = index;
        int left = 2 * index + 1;
        int right = 2 * index + 2; 

        if(left < heap.size() && heap.get(left).val < heap.get(position).val) {
            position = left;
        }

        if(right < heap.size() && heap.get(right).val < heap.get(position).val) {
            position = right;
        }

        if (position != index) {
            ListNode temp = heap.get(position);
            heap.set(position, heap.get(index));
            heap.set(index, temp);
            heapify(heap, position);
        }
    }

    public void minHeapify(ArrayList<ListNode> heap) {
        for (int i = heap.size()/2 - 1; i >= 0; i--) {
            heapify(heap, i);
        }
    }
}

Another Version: The time complexity is O(nk).

  1. /** 
  2.  * Definition for singly-linked list. 
  3.  * public class ListNode { 
  4.  *     int val; 
  5.  *     ListNode next; 
  6.  *     ListNode(int x) { 
  7.  *         val = x; 
  8.  *         next = null; 
  9.  *     } 
  10.  * } 
  11.  */  
  12. public class Solution {  
  13.     public ListNode mergeKLists(ArrayList<ListNode> lists) {  
  14.         ListNode head = null;  
  15.         ListNode current = null;  
  16.           
  17.         boolean isAllNull = false;  
  18.         while (!isAllNull) {  
  19.             isAllNull = true;  
  20.             ListNode min = null;  
  21.             int position = -1;  
  22.             for (int i = 0; i < lists.size(); i++) {  
  23.                 if (min == null && lists.get(i) != null) {  
  24.                     min = lists.get(i);  
  25.                     isAllNull = false;  
  26.                     position = i;  
  27.                 } else if (lists.get(i) != null){  
  28.                     isAllNull = false;  
  29.                     if (min.val > lists.get(i).val) {  
  30.                         min = lists.get(i);  
  31.                         position = i;  
  32.                     }  
  33.                 }  
  34.             }  
  35.             if (head == null) {  
  36.                 head = min;  
  37.                 current = min;  
  38.             } else {  
  39.                 current.next = min;  
  40.                 current = current.next;  
  41.             }  
  42.             if (position != -1) {  
  43.                 lists.set(position, lists.get(position).next);  
  44.             }  
  45.         }  
  46.         return head;  
  47.     }  
  48. }  
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ArrayList<ListNode> lists) {
        ListNode head = null;
        ListNode current = null;

        boolean isAllNull = false;
        while (!isAllNull) {
            isAllNull = true;
            ListNode min = null;
            int position = -1;
            for (int i = 0; i < lists.size(); i++) {
                if (min == null && lists.get(i) != null) {
                    min = lists.get(i);
                    isAllNull = false;
                    position = i;
                } else if (lists.get(i) != null){
                    isAllNull = false;
                    if (min.val > lists.get(i).val) {
                        min = lists.get(i);
                        position = i;
                    }
                }
            }
            if (head == null) {
                head = min;
                current = min;
            } else {
                current.next = min;
                current = current.next;
            }
            if (position != -1) {
                lists.set(position, lists.get(position).next);
            }
        }
        return head;
    }
}

转载出处:http://blog.csdn.net/beiyetengqing/article/details/7685593


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值