目录

  • 题目
  • 分析
  • 顺序合并
  • 最优解分治合并
  • 总结


题目

java 在两个有序链表中查找第K大元素 k个有序链表合并 java_数据结构

分析

首先你要会写合并两个有序链表,这个题目就是合并两个链表的变形,如果懂合并两个,那么合并k个也就不难了,只要弄一个遍历即可,一开始最前面两个合并,将合并的结果与第一个合并,以此类推,每次都进行两个两个合并,知道和最后一个合并完毕,思路都不难

顺序合并

import java.util.*;

public class Solution {
    public ListNode mergeKLists(ArrayList<ListNode> lists) {
        //思路:k个有序链表合并,就是进行多次两个有序链表的合并
        //首先若k=0,即为空,则直接返回null
        if(lists == null || lists.size() == 0){
            return null;
        }
        //若k=1,则直接返回这个链表,无需要排序
        if(lists.size() == 1){
            return lists.get(0);
        }
        //若k>1,则执行合并,先前两个合并,将合并后的结果再和后面的链表合并
        //遍历合并
        ListNode node = lists.get(0);
        for(int i = 1 ; i < lists.size() ; i++){
            node = mergeTwoList(node,lists.get(i));
        }
        return node;
    }
    
    private ListNode mergeTwoList(ListNode node1,ListNode node2){
        ListNode temp = new ListNode(-1);//头结点,记录两个合并的链表
        ListNode node = temp;//记录这个头结点,后面用于返回合并后的第一个节点node.next
        while(node1 != null && node2 != null){
            //小的先连到temp的后面
            if(node1.val < node2.val){
                temp.next = node1;
                node1 = node1.next;
            }else{
                temp.next = node2;
                node2 = node2.next;
            }
            temp = temp.next;
        }
        //若node1或者node2没有执行完,则直接连接到temp后面
        if(node1 != null){
            temp.next = node1;
        }
        if(node2 != null){
            temp.next = node2;
        }
        //返回合并后的第一个节点
        return node.next;
    }
}

java 在两个有序链表中查找第K大元素 k个有序链表合并 java_数据结构_02


下面是LeetCode,顺序合并

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        //合并k个有序链表就是合并两个有序链表的升级,只要遍历lists,两个两个合并即可
        ListNode res = null;
        int len = lists.length;
        for(int i = 0 ; i < len ; i++){
            res = mergeTwoList(res,lists[i]);
        }
        return res;
    }
    private ListNode mergeTwoList(ListNode l1, ListNode l2){
        //处理初始传递过程中存在的null
        if(l1 == null || l2 == null){
            return l1 == null ? l2 : l1;
        }
        //l1和l2均!=null,进行合并
        //创建一个头节点
        ListNode head = new ListNode(-1);
        ListNode cur = head;
        while(l1 != null && l2 != null){
            if(l1.val <= l2.val){
                cur.next = l1;
                cur = cur.next;
                l1 = l1.next;
            }else{
                cur.next = l2;
                cur = cur.next;
                l2 = l2.next;
            }
        }
        if(l1 != null){
            cur.next = l1;
        }
        if(l2 != null){
            cur.next = l2;
        }
        return head.next;
    }
}

java 在两个有序链表中查找第K大元素 k个有序链表合并 java_链表_03

最优解分治合并

java 在两个有序链表中查找第K大元素 k个有序链表合并 java_数据结构_04


先分,然后再归并

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null || lists.length == 0){
            return null;
        }
        //分治合并
        return merge(lists,0,lists.length - 1);
    }
    private ListNode merge(ListNode[] lists,int left,int right){
        //分治返回合并的结点
        if(left == right) return lists[left];
        //left != right
        int mid = (left + right) / 2;
        ListNode l1 = merge(lists,left,mid);//合并左半边
        ListNode l2 = merge(lists,mid+1,right);//合并右半边
        return mergeTwoLists(l1,l2);
    }

    //两两合并
    private ListNode mergeTwoLists(ListNode l1, ListNode l2){
        //处理初始传递过程中存在的null
        if(l1 == null || l2 == null){
            return l1 == null ? l2 : l1;
        }
        //l1和l2均!=null,进行合并
        //创建一个头节点
        ListNode head = new ListNode(-1);
        ListNode cur = head;
        while(l1 != null && l2 != null){
            if(l1.val <= l2.val){
                cur.next = l1;
                cur = cur.next;
                l1 = l1.next;
            }else{
                cur.next = l2;
                cur = cur.next;
                l2 = l2.next;
            }
        }
        if(l1 != null){
            cur.next = l1;
        }
        if(l2 != null){
            cur.next = l2;
        }
        return head.next;
    }
}

java 在两个有序链表中查找第K大元素 k个有序链表合并 java_算法_05

总结

当数据量大时,顺序合并和归并合并,速度基本不在一个量级,一个100ms+,一个1ms,所以我们这里用归并