LeetCode 刷题记录 23. Merge k Sorted Lists

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

Example:

Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
解法1:暴力法
调用mergeTwoLists函数 依次合并
c++:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeKLists(vector& lists) {
        int n = lists.size();
        if(n == 0) return nullptr;
        ListNode* ans = lists[0];
        for(int i = 1; i < n; i++){
            ans = mergeTwoLists(ans, lists[i]);
        }
        return ans;
    }
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (l1 == nullptr) return l2;
        if (l2 == nullptr) return l1;
        ListNode dummy(-1);
        ListNode* cur = &dummy;
        while(l1 && l2){
            if(l1->val <= l2->val){
                cur->next = l1;
                l1 = l1->next;
            } else {
                cur->next = l2;
                l2 = l2->next;
            }
            cur = cur->next;
        }
        cur->next = (l1 != nullptr) ? l1 : l2;
        return dummy.next;
        
    }
};

解法2:
Divide and Conquer Approach(分治法)

每次将问题分为两半,然后将链表两两合并,这样问题的规模就缩小一半,重复上述过程,直至只剩一个链表
链表数奇数 为了空出中间链表 需用(n + 1) / 2而不是n / 2 例如7个链表 k = (n + 1) / 2=4 0号链表和(0+4)=4 号链表合并 1号链表和(1+4)=5 号链表合并 2号链表和(2+4)=6号链表合并 空出中间3号链表不合并 注意 合并的次数为n / 2 次
链表数偶数 (n + 1) / 2和n / 2结果一样 为了和奇数保持一致 用(n + 1) / 2 例如6个链表 k = (n + 1) / 2=3 0号链表和(0+3)=3 号链表合并 1号链表和(1+3)=4 号链表合并 2号链表和(2+3)=5号链表合并 合并的次数为n / 2 次
c++:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeKLists(vector& lists) {
        int n = lists.size();
        if(n == 0) return nullptr;
        while(n > 1){
            int k = (n + 1) / 2;
            for(int i = 0; i < n / 2; i++){
                lists[i] = mergeTwoLists(lists[i], lists[i + k]);
            }
            n = k;
        }
        
        return lists[0];
    }
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (l1 == nullptr) return l2;
        if (l2 == nullptr) return l1;
        ListNode dummy(-1);
        ListNode* cur = &dummy;
        while(l1 && l2){
            if(l1->val <= l2->val){
                cur->next = l1;
                l1 = l1->next;
            } else {
                cur->next = l2;
                l2 = l2->next;
            }
            cur = cur->next;
        }
        cur->next = (l1 != nullptr) ? l1 : l2;
        return dummy.next;
        
    }
};

java:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        int n = lists.length;
        if(n == 0) return null;
        while(n > 1){
            int k = (n + 1) / 2;
            for(int i = 0; i < n / 2; i++){
                lists[i] = mergeTwoLists(lists[i], lists[i + k]);
            }
            n = k;
        }
        
        return lists[0];
    }
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) return l2;
        if (l2 == null) return l1;
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        
        while(l1 != null && l2 != null){
            if(l1.val <= l2.val){
                cur.next = l1;
                l1 = l1.next;
            } else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        cur.next = (l1 != null) ? l1 : l2;
        return dummy.next;
        
    }
}

Python:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        n = len(lists)
        if n == 0: return None
        while n > 1:
            k = (n + 1) / 2
            for i in range(n / 2):
                lists[i] = self.mergeTwoLists(lists[i], lists[i + k])
            
            n = k
        
        
        return lists[0]
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        if l1 == None:  return l2
        if l2 == None:  return l1
        dummy = ListNode(-1)
        cur = dummy
        
        while l1 != None and l2 != None:
            if l1.val <= l2.val:
                cur.next = l1
                l1 = l1.next
            else:
                cur.next = l2
                l2 = l2.next
            
            cur = cur.next
        
        cur.next = l1 if (l1 != None) else l2
        return dummy.next
        

解法3:优先级队列法
假设有三个链表
1,4,5
3,7,9
2,3,6
首先创建优先级队列,首先将所有链表的头结点入队列,即1,3,2入队,在优先级队列中自动按照大小顺序从小到达排好队 1,2,3,
建立头结点dummy和指向它的指针cur,取出优先级队列中的首个元素即1,加入目标链表,首先查看1是否有后继,如果有,将它即4加入优先级队列继续进行排列,最后直到优先级队列为空
c++:
cmp函数参数不能加引用,另外必须是a->val > b->val,表示从小到大排列,与结构体中的排序函数不同

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
struct cmp {
    bool operator() (const ListNode* a, const ListNode* b){
        return a->val > b->val;
    }  
};

class Solution {
    
public:
    ListNode* mergeKLists(vector& lists) {
        priority_queue, cmp> q;
        for(auto l : lists){
            if(l) q.push(l);
        }
        ListNode dummy(-1);
        ListNode* cur = &dummy;
        while(!q.empty()){
            auto temp = q.top();
            q.pop();
            cur->next = temp;
            cur = cur->next;
            if(cur->next) q.push(cur->next);
        }
        return dummy.next;
    }
    
};

java:

  1. 必须要处理lists为空的情况
  2. compare函数 如果返回负数 则o1 排在o2前面,返回0,优先级相等,返回正数,o1排在o2后面
    return o1.val - o2.val;实现了按值从小到大排列
  3. java中优先级队列 添加元素是add 获得队头元素是peek 删除元素并返回是poll
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null || lists.length == 0) return null;
        PriorityQueue q = new PriorityQueue(lists.length, new Comparator(){
            @Override
            public int compare(ListNode o1, ListNode o2){
                return o1.val - o2.val;
            }
        });
        for(ListNode l : lists){
            if(l != null) q.add(l);
        }
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        while(!q.isEmpty()){
            ListNode temp = q.peek();
            q.poll();
            cur.next = temp;
            cur = cur.next;
            if(cur.next != null) q.add(cur.next);
        }
        return dummy.next;
    }
    
}

Python:

  1. python2 的模块是Queue 而python3 的模块是queue
  2. 优先级队列加入元组,q.put((node.val,node)),根据前面结点的大小排序
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None
from Queue import PriorityQueue
class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        n = len(lists)
        q = PriorityQueue(maxsize = n)
        dummy = ListNode(None)
        cur = dummy
        for node in lists:
            if node: q.put((node.val,node))
        while q.qsize() > 0:
            temp = q.get()
            cur.next = temp[1]
            cur = cur.next
            if cur.next: q.put((cur.next.val,cur.next))
            
        
        return dummy.next
    
        

python3:
python3的优先级队列可能遇到不同的链表拥有相同的数值的结点会继续比较第二条件即结点,由于结点不能比较,所以报错
所以要给出第二条件 索引值idx 不同的链表的索引不同

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
from queue import PriorityQueue
class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        n = len(lists)
        q = PriorityQueue(maxsize = n)
        dummy = ListNode(None)
        cur = dummy
        for idx, node in enumerate(lists):
            if node: q.put((node.val,idx,node))
        while q.qsize() > 0:
            temp = q.get()
            idx, cur.next = temp[1], temp[2]
            cur = cur.next
            if cur.next: q.put((cur.next.val,idx,cur.next))
            
        
        return dummy.next

解法4:递归法
链表分为两段,递归的求解左半部分和右半部分,然后再用mergeTwoLists合并

c++:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */


class Solution {
    
public:
    ListNode* mergeKLists(vector& lists) {
        int n = lists.size();
        return partion(lists, 0, n - 1);
    }
    ListNode* partion(vector& lists, int start, int end) {
        if(start < end) return nullptr;
        if(start == end) return lists[start];
        int mid = start + (end - start) / 2;
        ListNode* left = partion(lists, start, mid);
        ListNode* right = partion(lists, mid + 1, end);
        return mergeTwoLists(left, right);
    }
     ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (l1 == nullptr) return l2;
        if (l2 == nullptr) return l1;
        ListNode dummy(-1);
        ListNode* cur = &dummy;
        while(l1 && l2){
            if(l1->val <= l2->val){
                cur->next = l1;
                l1 = l1->next;
            } else {
                cur->next = l2;
                l2 = l2->next;
            }
            cur = cur->next;
        }
        cur->next = (l1 != nullptr) ? l1 : l2;
        return dummy.next;
        
    }
};

java:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        int n = lists.length;
        return partion(lists, 0, n - 1);
    }
    public ListNode partion(ListNode[] lists, int start, int end) {
        if(start > end) return null;
        if(start == end) return lists[start];
        int mid = start + (end - start) / 2;
        ListNode left = partion(lists, start, mid);
        ListNode right = partion(lists, mid + 1, end);
        return mergeTwoLists(left, right);
    }
    
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) return l2;
        if (l2 == null) return l1;
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        
        while(l1 != null && l2 != null){
            if(l1.val <= l2.val){
                cur.next = l1;
                l1 = l1.next;
            } else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        cur.next = (l1 != null) ? l1 : l2;
        return dummy.next;
        
    }
}
    

python:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None
from Queue import PriorityQueue
class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        n = len(lists)
        return self.partion(lists, 0, n - 1)
    def partion(self, lists, start, end):
        if start > end: return None
        if start == end: return lists[start]
        mid = start + (end - start) / 2
        left = self.partion(lists, start, mid)
        right = self.partion(lists, mid + 1, end)
        return self.mergeTwoLists(left, right)
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        if l1 == None:  return l2
        if l2 == None:  return l1
        dummy = ListNode(-1)
        cur = dummy
        
        while l1 != None and l2 != None:
            if l1.val <= l2.val:
                cur.next = l1
                l1 = l1.next
            else:
                cur.next = l2
                l2 = l2.next
            
            cur = cur.next
        
        cur.next = l1 if (l1 != None) else l2
        return dummy.next
    
    
        

你可能感兴趣的:(LeetCode)