首页 > 编程语言 >算法:深挖合并 K 个有序链表

算法:深挖合并 K 个有序链表

时间:2023-08-04 20:22:04浏览次数:34  
标签:dummy ListNode 深挖 lists next 链表 算法 return null

本人刷题时思考的几个解法,欢迎交流
力扣链接:合并 2 个有序链表
力扣链接:合并K个有序链表


目录


合并 2 个有序链表

合并 2 个有序链表
操作模型:

for -> cur = min(list1 OR list2)

细节优化前:

class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode dummy = new ListNode(0);
        ListNode p = dummy;
        while(list1 != null || list2 != null){
            if(list1 == null){
                p.next = list2;
                break;
            } else if(list2 == null) {
                p.next = list1;
                break;
            }
            if(list1.val < list2.val){
                p.next = list1;
                list1 = list1.next;
            } else {
                p.next = list2;
                list2 = list2.next;
            }
            p = p.next;
        }
        return dummy.next;
    }
}

细节优化后:

class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if(list1 == null) return list2;
        if(list2 == null) return list1;

        ListNode dummy = new ListNode(0);
        ListNode cur = dummy;
        ListNode p1 = list1;
        ListNode p2 = list2;

        while(p1 != null && p2 != null) {
            if(p1.val < p2.val){
                cur.next = p1;
                p1 = p1.next;
            } else {
                cur.next = p2;
                p2 = p2.next;
            }
            cur = cur.next;
        }
        cur.next = p1 != null ? p1 : p2;
        return dummy.next;
    }
}

合并 k 个有序链表

K 个中 minNode

每次迭代,比较 K 个链表头,求最小值 minNode,加入返回链表
直到迭代完所有链表
时间复杂度 O(K * N)
运行时间:210ms
操作模型:

for -> (cur = min(lists.forEach -> node))

优化细节前代码:

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null) return null;
        if(lists.length == 0) return null;

        ListNode dummy = new ListNode(0);
        ListNode cur = dummy;

        ListNode min;
        int minPos;
        boolean keep = true;

        while(keep){
            keep = false;
            minPos = 0;
            min = lists[0];
            
            for(int p = 0; p < lists.length; p++) {
                if(lists[p] == null) continue;

                if(keep != true) keep = true;

                if(min == null || (lists[p]).val < min.val) {
                    min = lists[p];
                    minPos = p;
                }
            }

            if(keep != true) break;

            cur.next = min;
            lists[minPos] = min.next;
            cur = cur.next;
        }

        return dummy.next;
    }
}

优化细节后:

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        ListNode dummy = new ListNode(0);
        ListNode cur = dummy;

        ListNode minNd;
        int minPos;

        while(true){
            minPos = -1;
            minNd = null;
            
            for(int i = 0; i < lists.length; i++) {
                if(lists[i] == null) continue;

                if(minNd == null || lists[i].val < minNd.val) {
                    minNd = lists[i];
                    minPos = i;
                }
            }
            if(minPos == -1) break;

            cur.next = minNd;
            lists[minPos] = lists[minPos].next;
            cur = cur.next;
        }

        return dummy.next;
    }
}

排序队列取minNode队头

手动实现的排序队列

运行时间:226ms

class Solution {
    static class SortedQueue {
        private static final LinkedList<ListNode> list = 
			new LinkedList<>();

        ListNode popHead() {
            return list.removeFirst();
        }
        void sortedPut(ListNode insert){
            if (insert == null) return;
            int index = 0;
            for (ListNode node : list) {
                if (node.val >= insert.val){
                    list.add(index, insert);
                    return;
                }
                index++;
            }
            if (index != 0){
                list.addLast(insert);
            } else {
                list.addFirst(insert);
            }
            return;
        }
        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            for (ListNode node : list){
                builder.append(node.val).append(" ");
            }
            return builder.toString();
        }
    }
}

未加嵌套的单次逻辑:

public ListNode mergeKLists(ListNode[] lists) {
     ListNode dummy = new ListNode(0);
     ListNode p = dummy;

     SortedQueue queue = new SortedQueue();

     p.next = queue.popHead();
     if(p.next.next != null){
        queue.sortedPut(p.next.next);
     }
     p = p.next;
 }

加入嵌套、嵌套退出的条件:

while(queue.list.size() != 0){ ...... }

完整代码:

class Solution {
    static class SortedQueue {
        static final LinkedList<ListNode> list = new LinkedList<>();

        ListNode popHead() {
            return list.removeFirst();
        }
        void sortedPut(ListNode insert){
            if (insert == null) return;
            int index = 0;
            for (ListNode node : list) {
                if (node.val >= insert.val){
                    list.add(index, insert);
                    return;
                }
                index++;
            }
            if (index != 0){
                list.addLast(insert);
            } else {
                list.addFirst(insert);
            }
            return;
        }
    }

    public ListNode mergeKLists(ListNode[] lists) {
        ListNode dummy = new ListNode(0);
        ListNode p = dummy;

        SortedQueue queue = new SortedQueue();
        for(ListNode node : lists){
            queue.sortedPut(node);
        }

        while(queue.list.size() != 0){
            p.next = queue.popHead();
            if(p.next.next != null){
                queue.sortedPut(p.next.next);
            }
            p = p.next;
        }
        return dummy.next;
    }
}

优先级队列

class Solution {
   public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) return null;
        PriorityQueue<ListNode> queue = new PriorityQueue<>(lists.length, new Comparator<ListNode>() {
            @Override
            public int compare(ListNode o1, ListNode o2) {
                if (o1.val < o2.val) return -1;
                else if (o1.val == o2.val) return 0;
                else return 1;
            }
        });
        ListNode dummy = new ListNode(0);
        ListNode p = dummy;
        for (ListNode node : lists) {
            if (node != null) queue.add(node);
        }
        while (!queue.isEmpty()) {
            p.next = queue.poll();
            p = p.next;
            if (p.next != null) queue.add(p.next);
        }
        return dummy.next;
    }
}

分治

运行时间:1ms

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null || lists.length == 0){
            return null;
        }
        return spilt(lists , 0 , lists.length - 1);
    }
    public ListNode spilt(ListNode[] lists , int i , int j){
        if(i == j){
            return lists[i];
        }
        int m = (i + j) >>> 1;
        ListNode left = spilt(lists , i , m);
        ListNode right = spilt(lists , m+1 , j);
        return mergeTwoLists(left, right);
    }
    public ListNode mergeTwoLists(ListNode p1, ListNode p2) {
        ListNode s = new ListNode(-1, null);
        ListNode p = s;
        while (p1 != null && p2 != null) {
            if (p1.val < p2.val) {
                p.next = p1;
                p1 = p1.next;
            } else {
                p.next = p2;
                p2 = p2.next;
            }
            p = p.next;
        }
        p.next = p1 != null ? p1 : p2;
        return s.next;
    }
}

标签:dummy,ListNode,深挖,lists,next,链表,算法,return,null
From: https://www.cnblogs.com/luoyicode/p/17606982.html

相关文章

  • c++算法之离散化例题
    离散化基础2题目描述给定 n 个元素的数列,将相同的数据离散化为一个数据(去重),即把 {4000,201,11,45,11}{4000,201,11,45,11} 离散化为 {4,3,1,2,1}{4,3,1,2,1}。输入格式第一行一个整数 (1≤m≤105)n(1≤n≤105),为元素的个数。第二行 n 个用空格隔天的整数a[i](−109......
  • ICCV论文速读:SOTA!越简单,越强大!ByteTrackV2-通用2D、3D跟踪算法(开源)
    前言 本文提出了一个分层的数据关联策略来寻找低分检测框中的真实目标,这缓解了目标丢失和轨迹不连续的问题。这个简单通用的数据关联策略在2D和3D设置下都表现良好。另外,由于在3D场景中预测对象在世界坐标系中的速度比较容易,本文提出了一种辅助的运动预测策略,将检测到的速度与卡......
  • GO:用链表实现栈的操作
         ......
  • 入职就40W起,推荐系统何以成为算法皇冠?
    最近推荐系统越来越火爆了BOSS直聘2020年四季度人才吸引力报告显示,推荐算法已经连续2年成为平均薪资最高的岗位,平均年薪高达近40W。大厂必备核心——推荐系统从商业角度来讲,互联网主要起到平台作用,构建多方沟通桥梁,例如淘宝对应卖家和卖家,头条是信息产出方和读者,除了要满足用户本身......
  • 华为月薪6W招视觉算法工程师,看到要求我傻眼了!
    对程序员来说,学历重要还是技术重要?IT圈曾无数次讨论过这个问题。有人说,只要写得出代码,管你大专还是硕士,都是好程序员。反对的人讲,如今学计算机的人数众多,早就不是上个培训班就能找到工作的年代了。那么,IT界的学历到底值不值钱?的确,互联网野蛮生长时代,对求职者的学历背景宽容度极高。......
  • 记一次JavaScript异或算法加密 , 异或加密
     公司业务代码constBase64=require('base-64')functionxorEncrypt(str,key){letresultconstlist=[]for(leti=0;i<str.length;i++){constcharCode=str.charCodeAt(i)^key.charCodeAt(i%key.length)list.push(String.......
  • 代码随想录算法训练营第六天|力扣454.四数相加II、力扣383.赎金信、力扣15.三数之和、
    四数相加II(力扣454.)前两个数组的值直接遍历,并将和存入map中,key为和,value为出现次数后两个数组再次遍历,在map中寻找是否存在0-(c+d),若存在,count+=valuefor(a:A){//遍历ABfor(b:B){map[a+b]++;}}//insert操作for(c:C){for(d:D){target=0-(c+d);if(map.containsKey(t......
  • 国密算法SM2介绍
    国密算法是我国自主研发创新的一套数据加密处理系列算法。从SM1-SM4分别实现了对称、非对称、摘要等算法功能。特别适合应用于嵌入式物联网等相关领域,完成身份认证和数据加解密等功能。当然,默认的前提条件是算法密钥必须保证安全性,因此要将国密算法嵌入到硬件加密芯片中结合使用。......
  • 反转链表系列图解
    1.反转链表给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。图解代码实现publicListNodeReverseList(ListNodehead){ListNodecur=head;ListNodepre=null;ListNodenext=null;......
  • dijkstra算法
    【USACO】热浪#include<bits/stdc++.h>usingnamespacestd;structnode{ intu,dist; node(int_u,int_dist) { u=_u; dist=_dist; }};structnode2{ intv,w; node2(int_v,int_w) { v=_v; w=_w; }};structcmp{ booloperator()(nodea,nod......