你如何计算算法的大O.

时间:2014-12-18 14:43:16

标签: arrays algorithm big-o time-complexity

我遇到一个问题,我必须在数组中找到缺少的数字并将它们添加到一个集合中。

问题是这样的:

大小(n-m)的数组,数字来自1..n,其中m个缺失。

在O(日志)中找到所有缺失的数字。数组已排序。 示例:

n = 8

arr = [1,2,4,5,6,8]

m = 2

结果必须是{3,7}。

到目前为止,这是我的解决方案,想知道如何计算解决方案的大部分内容。我见过的大多数解决方案都使用了分而治之的方法。我如何计算下面的算法的大哦?

ps如果我不符合要求,有什么方法可以做到这一点,而不必递归吗?我真的不是递归的粉丝,我简直无法理解它! :(

var arr = [1,2,4,5,6,8];
var mySet = [];

findMissingNumbers(arr);

function findMissingNumbers(arr){
    var temp = 0;
    for (number in arr){                    //O(n)
        temp = parseInt(number)+1;
        if(arr[temp] - arr[number] > 1){
            addToSet(arr[number], arr[temp]);
        }
    }
}

function addToSet(min, max){

    while (min != max-1){
        mySet.push(++min);
    }
}

4 个答案:

答案 0 :(得分:2)

你想要看两件事,你已经指出了一件事:你为循环“for(number in arr)”迭代了多少次?如果数组包含n-m个元素,那么这个循环应该迭代n-m次。然后查看您在循环中执行的每个操作,并尝试找出每个操作的最坏情况(或典型)方案。 temp = ...行应该是一个恒定的成本(比如每个循环1个单元),条件是常量成本(比如每个循环1个单元),然后是addToSet。 addToset更难以分析,因为它不是每次都调用,而且每次调用它的成本可能会有所不同。所以也许你想要的是,对于m个缺失元素中的每一个,addToSet将执行1次操作...总共m次操作(你不知道它们何时会发生,但是所有m必须发生在某一点)。然后将所有费用加起来。

nm循环迭代,在每一个中你做2个操作总共2个(nm)然后加上addToSet完成的m个操作,总共有2n-m~2n(假设m比n小)。这可能是O(n-m)或O(n)(如果它是O(n-m),它也是O(n),因为n> = n-m。)希望这有帮助。

答案 1 :(得分:1)

在你的代码中,你有一个复杂的O(n),因为你检查了数组的n索引。更快的方法就是这样:

  • 转到数组的一半
  • 这个数字是否在正确的位置(这个 意味着其他的也是因为数组已经排序了)
  • 如果是预期的数字:转到下半场的一半
  • 如果不是:在集合中添加此号码并转到上半部分的一半
  • 当您查看的数字为索引大小-1
  • 时停止

请注意,您可以进行一些优化,例如,您可以直接检查数组是否具有正确的大小并返回空数组。这取决于你的问题。

我的算法也在O(n)中,因为你总是采用最差的数据集。就我而言,我会错过阵列末尾的一个数据。所以从技术上来说它应该是O(n-1)但是在n前面的常数可以忽略不计(假设非常高)。这就是为什么你必须记住平均复杂性。

答案 2 :(得分:0)

这里的价值是一个更简洁的算法实现(javascript):

var N = 10;
var arr = [2,9];
var mySet = [];
var index = 0;
for(var i=1;i<=N;i++){
    if(i!=arr[index]){
        mySet.push(i);
    }else{
        index++;
    }
}

这里的大(O)是微不足道的,因为只有一个循环,它每次迭代都会以恒定的成本运算精确运行N次。

答案 3 :(得分:-2)

Big O是算法的复杂性。它是程序提出解决方案所需步骤数的函数。

这给出了很好的解释:

Big O, how do you calculate/approximate it?