leetcode hard模式专杀之23 merge k sorted lists

44 篇文章 0 订阅
35 篇文章 0 订阅

这个题目思路不算很复杂,但是容易出错,leetcode把它算作hard模式的题目,我看在medium在hard之间,不过如果面试的时候碰到,也就坑死爹。


思路如下:


假设每个链表从小到大排列,头是最小值,则每次从所有链表头中找出最小值, 然后把它摘下来,放到结果链表中,从k个值中找到最小值,不是个难事,不过如果每次都去计算,哪怕用一次冒泡,算法复杂度也是够呛的,因为摘下来后最小值又要重算更新,所以思路是以空间换时间,额外用一个链表记录当前所有链表头的值,该链表维持大小顺序,那么每次更新该链表时,只要找到一个合适的位置插入即可,为了使得这个插入动作不至于是O(n)的时间复杂度,可使用二分法查找插入点(一开始我没用二分法,也能完成功能,但是时间复杂度就直接过不了leetcode oj)。 所以接下来的操作,就是循环取最小链表头,更新最小值链表队列,直到最小值链表队列为空。代码如下(注意,这个代码是我在eclipse里跑的,不能直接贴到 leetcode里,要贴的话需要自己把相应的函数copy过去):




import java.util.ArrayList;

import java.util.List;



public class test {



    private static class ListNode {
        int val;
        ListNode next;
        ListNode(int x) { val = x; }
    }

    private static class MyPair{
        int index;
        int ln;
        MyPair(int i, int n){
            this.index = i;
            this.ln = n;
        }
    }

    private static void orderInsert(List<MyPair> orderList, MyPair val){
        if(orderList.isEmpty()){
            orderList.add(val);
        }else{
            int end = orderList.size()-1;
            innerInsert( orderList, val, 0, end);
//            int i = 0;
//            while(i<orderList.size() && orderList.get(i).ln<=val.ln){
//                i++;
//            }
//            orderList.add(i, val);
        }
    }

    private static void innerInsert( List<MyPair> orderList, MyPair val, int start, int end){
        if(start>end){
            return;
        }
        if(start==end){
            if(orderList.get(start).ln<val.ln){
                orderList.add(start+1, val);
            }else{
                orderList.add(start, val);
            }
            return;
        }

        int mid = (start+end)/2;
        if(orderList.get(mid).ln<val.ln){
            innerInsert(orderList, val, mid+1, end);
        }else{
            innerInsert(orderList, val, start, mid);
        }

    }

    public static ListNode mergeKLists(ListNode[] lists) {
        ListNode result = null;
        List<MyPair> orderList = new ArrayList();

        // initialize oderlist
        int index = 0;
        for(ListNode ln: lists){
            if(ln!=null){
                orderInsert(orderList, new MyPair(index, ln.val));
            }
            index++;
        }

        //update oderlist by doing the 3 steps:
        // 1. get the first element in orderlist, remove head and add it to result from the corresponding index list
        // 2. remove first element from oder list
        // 3. update oderlist by orderInsert from the updated list new head if new head is not null
        // 4. go back to step1, until order list is empty
        while(!orderList.isEmpty()){
            int currentMin = orderList.get(0).index;
            ListNode minList = lists[currentMin];
            if(minList==null){
                orderList.remove(0);
                continue;
            }
            if(result==null){
                lists[currentMin] = minList.next;
                result = minList;
                minList.next = null;
            }else{
                lists[currentMin] = minList.next;
                minList.next = result;
                result = minList;
            }
            orderList.remove(0);
            if(lists[currentMin]!=null){
                orderInsert(orderList, new MyPair(currentMin, lists[currentMin].val));
            }
        }

        return revert(result);
     //   return result;
    }

    private static ListNode revert(ListNode result){

        if(result == null){
            return result;
        }
        ListNode inode = result;

        if(inode.next==null){
            //single node
            return result;
        }

        ListNode jnode=inode.next;
        inode.next = null;

        while(true){
            ListNode tmpNode = jnode.next;
            if(tmpNode == null){
                jnode.next = inode;
                result = jnode;
                return result;
            }
            jnode.next = inode;
            inode = jnode;
            jnode=tmpNode;
        }

    }

    public static void myIterate(ListNode ln){
        ListNode p = ln;
        while(p!=null){
            System.out.println(p.val);
            p = p.next;
        }
        System.out.println("=============");
    }

    public static void main(String[] args) throws Exception {
        ListNode n11 = new ListNode(1);
        ListNode n12 = new ListNode(2);
        ListNode n13 = new ListNode(3);
        n11.next = n12;
        n12.next = n13;


        ListNode n21 = new ListNode(4);
        ListNode n22 = new ListNode(8);
        ListNode n23 = new ListNode(9);
        n21.next = n22;
        n22.next = n23;

        ListNode n31 = new ListNode(5);
        ListNode n32 = new ListNode(6);
        ListNode n33 = new ListNode(7);
        n31.next = n32;
        n32.next = n33;


        ListNode[] ll = {n11, n21, n31};

        ListNode result = mergeKLists(ll);

        myIterate(result);

		/*
		List<String> tt  = new ArrayList();
		tt.add("a");
		tt.add("b");
		tt.add("c");
		tt.add(3, "d");
		System.out.println(tt);*/
    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值