LeetCode-23-合并K个升序链表(分治,优先队列)

题目

在这里插入图片描述

思路

  1. 想法肯定是K指针,但是这样做感觉复杂度太高了,再阴间一点就是遍历链表数组,全部加入一个vector或者arrrylist里,然后一个sort然后再建链表,但肯定不是考察这方面。直接润去题解。
  2. 首先了解一下如果是两个升序链表,规定需要O(1)的空间复杂度,那么不能使用双指针了(顺带一提,原来看起来最简洁的方法是递归,我为一直只知道双指针羞愧…)
  3. 于是重新回去写一遍链表合并,使用O(1)空间复杂度的方式,链接:https://blog.csdn.net/z754916067/article/details/123386965
  4. 第一种方法:在采用合并双链表的基础上,建立一个空指针ans,然后每一步把它和K个之一进行双合并。
  5. 第二种方法:分治法,建立在递归和两个链表合并的基础上,每次合并两个链表,再将合并好后的链表合并成大一点的链表,再合并,后附代码。
  6. 第三种方法:优先队列法,其实想法大致和K指针差不多,只是把比较过程采用了优先队列进行容纳,以大小为优先级,每次优先队列出的是最小的一个node。

代码(分治法)

    public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        //一开始设定一个头节点 作为新list的头节点
        ListNode head = new ListNode();
        //同样还是双指针
        ListNode l1 = list1;
        ListNode l2 = list2;
        //记录现在的指针指到哪里了
        ListNode now = head;
        while(l1!=null && l2!=null){
            if(l1.val==l2.val){
                now.next=l1;
                now=l1;
                l1=l1.next;
                now.next=l2;
                now=l2;
                l2=l2.next;
            }else if(l1.val< l2.val){
                now.next=l1;
                now=l1;
                l1=l1.next;
            }else{
                now.next=l2;
                now=l2;
                l2=l2.next;
            }
        }
        if(l1==null) now.next=l2;
        else if(l2==null) now.next=l1;
        return head.next;
    }
    public static ListNode mergeKLists(ListNode[] lists) {
          int l=0;
          int r = lists.length-1;
          return merge(lists,l,r);
    }
    public static ListNode merge(ListNode[] list1,int l,int r){
          if(l==r) return list1[l];
          if(l>r) return null;
          int mid = (l+r)>>1;
        //返回的是经过双合并的ListNode 因为两个会合成一个
        //合并的对象其中之一是之前合并好了的
        return mergeTwoLists(merge(list1,l,mid),merge(list1,mid+1,r));
    }

代码(优先队列)

    public  ListNode mergeKLists(ListNode[] lists) {
          //创建一个优先队列,以数值大小作为优先级
        Queue<ListNode> pq = new PriorityQueue<>((v1, v2) -> v1.val - v2.val);
        for (ListNode node: lists) {
            if (node != null) {
                //把数组里每个链表的根节点加入
                pq.offer(node);
            }
        }

        //新链表的头部和尾部 
        ListNode Head = new ListNode(0);
        ListNode tail = Head;
        while (!pq.isEmpty()) {
            //找出最小的node 并把它后面的加入队列中
            ListNode minNode = pq.poll();
            tail.next = minNode;
            tail = minNode;
            if (minNode.next != null) {
                pq.offer(minNode.next);
            }
        }
        return Head.next;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值