在不使用额外内存的情况下计算合并预先排序列表的时间复杂度

时间:2017-02-08 14:58:39

标签: java algorithm time-complexity mergesort

给定一个预先排序的数组列表,即List<List<Integer>>,我使用以下技术对它们进行排序。有人请向我解释时间的复杂性吗?这是算法

List<Integer> merge(List<List<Integer>> lists){
    Queue<MyPriorityQueue> pqs = new LinkedList<>();
    for(int i=1; i<lists.size();i+=2){
        pqs.add(merge(lists.get(i-1),lists.get(i)));
    }
    if(lists.size()%2==1)pqs.add(merge(lists.get(lists.size()-1),null));

    while(pqs.size()>1) pqs.add( merge(pqs.poll(),pqs.poll()));

    MyPriorityQueue myPq = pqs.poll();
    List<Integer> results = new ArrayList<>();

    while(!myPq.isEmpty()){
        result.add(myPq.poll());
    }
    return result;
}

有两种merge方法。

MyPriorityQueue merge(List<Integer> a, List<Integer> b){ return new MyPriorityQueue(a,b);}

MyPriorityQueue merge(MyPriorityQueue a, MyPriorityQueue  b){ return new MyPriorityQueue(a,b);}

请注意,merge函数实际上将两个迭代器传递给MyPriorityQueue构造函数。因此,当调用MyPriorityQueue#poll()时,将比较两个迭代器并返回更大的值。因此,我们没有使用额外的内存。

现在让我们与普通的mergeSort进行比较。通常mergeSort使用额外的内存:每次调用merge(x,y)只会创建第三个列表z并将x和y中的所有元素放入z中。该方法将导致时间O(n lg n)。但在我目前的方法中,我们并没有使用额外的内存。因此每次调用#poll()时,我都必须走树才能找到最小的元素。这对我来说意味着行while(!myPq.isEmpty()){result.add(myPq.poll());}的O(n ^ 2)。但是有人告诉我时间复杂度实际上仍然是O(n lg n)。我看不出怎么样。有人请向我解释时间复杂度吗?

我们没有进行n次比较n次,是吗?根据我的可视化,如果树上有n个列表并且我调用myPq.poll()),那么我们正在进行n次比较。

所以基本上让我们说有n个列表,每个列表中平均有k个元素。我认为算法的时间复杂度

log n + (n+k)*n。创建pqs树并获取根目录需要log n;然后将(n + k)* n作为while(!myPq.isEmpty()){result.add(myPq.poll());}

添加到结果中的所有元素

更新:这是Java中的实际实现

import java.util.*;


public class MergePresortedLists {


    List<Integer> merge(List<List<Integer>> lists) {

        Queue<PQ> pqs = new LinkedList<>();

        for (int i = 1; i < lists.size(); i += 2) {

            pqs.add(merge(lists.get(i - 1), lists.get(i)));

        }

        if (lists.size() % 2 != 0)

            pqs.add(merge(lists.get(lists.size() - 1), null));

        while (pqs.size() > 1) {

            pqs.add(merge(pqs.poll(), pqs.poll()));

        }

        PQ pq = pqs.poll();


        List<Integer> result = new ArrayList<>();

        while (!pq.isEmpty()) {

            result.add(pq.poll());

        }

        return result;

    }


    private PQ merge(List<Integer> a, List<Integer> b) {

        return new PQ(a, b);

    }


    private PQ merge(PQ a, PQ b) {

        return new PQ(a, b);

    }


    class PQ {


        List<Integer> a, b;

        int sizeA = -1, sizeB = -1;


        PQ x, y;


        public PQ(List<Integer> l1, List<Integer> l2) {

            a = l1;

            b = l2;

            if (null != a)

                sizeA = a.size() - 1;

            if (null != b)

                sizeB = b.size() - 1;

        }


        public PQ(PQ q1, PQ q2) {

            x = q1;

            y = q2;

        }


        public int size() {

            int listsSize = sizeA + sizeB + 2;

            int qSize = null == x ? 0 : y.size();

            qSize += null == y ? 0 : x.size();

            return listsSize > qSize ? listsSize : qSize;

        }


        public boolean isEmpty() {

            return size() == 0;

        }


        public Integer poll() {

            if (sizeA > -1 || sizeB > -1) {

                return listPoll();

            }


            Integer xPeek = (x != null && !x.isEmpty()) ? x.peek() : null;

            Integer yPeek = (y != null && !y.isEmpty()) ? y.peek() : null;

            if (null != xPeek || null != yPeek) {

                return qPoll(xPeek, yPeek);

            }

            return null;

        }


        private Integer listPoll() {

            if (sizeA > -1 && sizeB > -1) {

                return a.get(sizeA) > b.get(sizeB) ? a.get(sizeA--) : b.get(sizeB--);

            } else if (sizeA > -1)

                return a.get(sizeA--);

            else

                return b.get(sizeB--);

        }


        private Integer qPoll(Integer xPeek, Integer yPeek) {

            if (null != xPeek && null != yPeek) {

                return xPeek > yPeek ? x.poll() : y.poll();

            } else if (null != xPeek)

                return x.poll();

            else

                return y.poll();

        }


        public Integer peek() {

            if (sizeA > -1 || sizeB > -1) {

                return listPeek();

            }


            Integer xPeek = null != x ? x.peek() : null;

            Integer yPeek = null != y ? y.peek() : null;

            if (null != xPeek || null != yPeek) {

                return qPeek(xPeek, yPeek);

            }

            return null;

        }


        private Integer listPeek() {

            if (sizeA > -1 && sizeB > -1) {

                return a.get(sizeA) > b.get(sizeB) ? a.get(sizeA) : b.get(sizeB);

            } else if (sizeA > -1)

                return a.get(sizeA);

            else

                return b.get(sizeB);

        }

        private Integer qPeek(Integer xPeek, Integer yPeek) {

            if (null != xPeek && null != yPeek) {

                return xPeek > yPeek ? xPeek : yPeek;

            } else if (null != xPeek) return xPeek;

            else return yPeek;

        }

    }

}

0 个答案:

没有答案