程序制作的Big-O运行时

时间:2018-11-29 01:10:22

标签: java list time heap big-o

我正在尝试创建在特定时间运行的代码。我的第一种方法应该在O(log k)中以最差的方式运行。这是我的方法:

public void count(T x) {
    if(heap.size() < k){
        heap.add(x);
    }
    else if(heap.size() == k && x.compareTo((T) heap.peek()) > 0){
        heap.remove(); 
        heap.add(x);
    }
}

我无法计算运行时间。我敢肯定,heap.size()调用是恒定时间。尽管add()方法在O(log k)时间中运行。 remove()方法也是如此。其他比较也应该只花费固定的时间。因此,我很确定我的程序在O(log k)中运行。有人可以确认吗?

我的另一种方法应该在O(k log k)时间中运行。这是我的方法:

public List<T> kbest() {
    //empty queue first and then restore
    List<T> list = new ArrayList<T>();
    int size = heap.size(); 
    for(int i = 0; i < size; i++){
        list.add(0, heap.poll());
    }
    for(int j = 0; j < list.size(); j++){
        heap.add(list.get(j));
    }
    return list;
}

这个让我更困惑。列表中的add()以恒定的时间运行。而堆中的add()在O(log k)中运行。获取堆的大小是恒定的,列表的大小也是恒定的(完成“ j”次)。这会使我的运行时O(n)变成线性吗?

1 个答案:

答案 0 :(得分:2)

我们一行一行地做。

public void count(T x) {
    if(heap.size() < k){ // O(1)
        heap.add(x); // O(log k)
    }
    else if(heap.size() == k && // O(1)
                x.compareTo(
                    (T) heap.peek()) > 0) { // O(1)
        heap.remove(); // O(log k)
        heap.add(x); // O(log k)
    }
}
  1. 如果它进入if块:O(1 * log k),即O(log k)
  2. 如果它进入else if块:O(max(1, 1) * max(log k, log k)),即O(log k)
  3. 您是正确的-此方法为O(log k)

现在第二种方法:

public List<T> kbest() {
    //empty queue first and then restore
    List<T> list = new ArrayList<T>();
    int size = heap.size();  // O(1)
    for(int i = 0; i < size; i++) { // O(n)
        list.add(0, heap.poll()); // O(n)
    }
    for(int j = 0; j < list.size(); j++){ // O(n)
        heap.add(list.get(j)); // O(log n)
    }
    return list;
}
  1. heap.sizeO(1)
  2. 第一个for循环是O(n * n),即O(n^2)
  3. 第二个for循环是O(n * log n),即O(n log n)
  4. 最终复杂度为O(max(1, n^2, n log n)),即O(n^2)

更新

要提高kbest()的时间复杂度,可以使用add()的{​​{1}}方法。

当然,顺序会相反。您可以轻松使用O(1),即Collections.reverse(list)。由于这将在循环外部执行,因此时间复杂度不会成倍增加。