如何计算程序的Big O复杂度?

时间:2011-04-01 22:45:56

标签: java big-o

我有一个大O符号问题。假设我有一个执行以下操作的Java程序:

  1. 将一个整数数组读入HashMap,以跟踪数组中存在的整数的出现次数。 [1,2,3,1]将是[1-> 2,2-> 1,3-> 1]。

  2. 然后我从HashMap抓取密钥并将其放入Array

    Set<Integer> keys = dictionary.keySet();
    Integer[] keysToSort = new Integer[keys.size()];
    keys.toArray(keysToSort);
    
  3. 使用keyArray对<{1}}进行排序。

  4. 然后遍历已排序的Arrays.sort抓取keyArray中的相应值,以显示或格式化结果。

  5. 我想我知道以下内容:

    • 步骤1是O(n)
    • 如果我要相信Java API
    • ,则步骤3为O(n log n)
    • 步骤4是O(n)

    • 第2步:在进行此类计算时,我应该知道Java如何实现HashMapSet方法。我会假设它遍历toArray检索HashMap。如果是这种情况,我会假设其为O(n)。

    如果顺序操作指示我添加每个部分,那么最终的计算将是 O(n + n·log n + n + n)= O(3n + n·log n)。

    跳过常数,你有 O(n + n log n)。这可以进一步减少还是我完全错了?

6 个答案:

答案 0 :(得分:6)

我相信O(n + nlogn)可以进一步简化为O(nlogn)。这是因为nnlogn相比渐渐变得无意义,因为它们是复杂的不同顺序。 nlogn的排序高于n。这可以通过向下滚动到公共功能顺序部分在wikipedia page上进行验证。

答案 1 :(得分:2)

当使用哈希映射等复杂数据结构时,您需要知道它如何检索对象,并非所有数据结构都具有相同的检索过程或时间来检索元素。

这可以帮助您在Java中找到复杂数据类型的大O: http://www.coderfriendly.com/wp-content/uploads/2009/05/java_collections_v2.pdf

答案 2 :(得分:0)

  • 第2步需要O(地图容量)。

  • 如果您有许多具有相同哈希码的密钥(即O(这些密钥的数量)用于单个查找或更改,则步骤1和4可能会变坏,再乘以数量那些查找/更改)。

  • O(n + n·log n)= O(n·log n)

答案 3 :(得分:0)

关于第2步,您可以稍微担心一下。据我所知,Java API没有指定这些操作的运行时间。

至于O(n + n log n) Treebranch是对的。您可以将其减少到O(n log n),因为对于某些基本值n0 n log n > c*n forall c /= 0, n > n0,显然就是这种情况,因为无论您为c选择了什么号码,都可以使用n0设置为2^c+1

答案 4 :(得分:0)

首先,

如果将O(n)中的整数插入HashMap,则步骤1仅为O(1)。在Perl中,插入哈希值的最坏情况是O(N) N个项目(也称为摊销O(1)),如果您折扣密钥的长度(这是可接受的) 。 HashMap可能效率较低,具体取决于它如何解决某些问题。

其次,

O(N)O(N log N),因此O(N + N log N)O(N log N)

答案 5 :(得分:0)

大O没告诉你的一件事是缩放因子有多大。它还假设您有一台理想的机器。这很重要的原因是从文件中读取的内容可能远远超过其他任何内容。

如果你确实计时,你会收到startup cost + read time的内容。即使是一百万条记录,启动成本也可能是最大的。读取时间与读取的字节数有关(即数字长度可能很重要)如果你有1亿读取时间可能更重要。如果您有十亿条记录,则很多将取决于唯一条目的数量而不是条目的总数。唯一条目的数量限制在20亿左右。

顺便说一句:要更有效地执行计数,请尝试使用TIntIntHashMap,它可以最大限度地减少对象创建,使其快几倍。

当然我只谈论大O不考虑的真机;)

我要说的是你可以做一个大的O计算,但它不会提供有关真实应用程序行为的信息。