【问题标题】:Analysis of array algorithm and its time complexity数组算法及其时间复杂度分析
【发布时间】:2016-06-17 13:45:16
【问题描述】:

我应该分析这段代码并说明它的时间复杂度,但我无法理解代码本身的作用,它如何改变数组 a?

下面两个操作我也看不懂: 1) foobar[a[i]]++; 所以你用数组 a 的元素替换 foobar 中的零?但是 ++ 有什么作用呢?

2) a[outPos++]=1; 这首先增加 outPos,并在整个 for 循环期间保持 a[0] 不变?

public static void foo(int[] a, int b) {
    int [] foobar = new int[b+1];
    for (int i = 0; i<foobar.length; i++)
        foobar[i]=0;
    for (int i = 0; i<a.length; i++)
        foobar[a[i]]++;
    int outPos = 0;
    for (int i=0; i<foobar.length; i++)
        for (int j=0; j<foobar[i]; j++)
            a[outPos++]=i;
}

就时间复杂度而言,我认为是 O(n^2)。前两个 for 循环在恒定时间内运行。但是在我看来,第三个嵌套循环的最坏情况是 foobar 中的最后一个元素很大,然后它会是二次的?

【问题讨论】:

    标签: java arrays algorithm time


    【解决方案1】:

    Counting Sort的实现,

    其中a[]存储要排序的数组,ba[]中的最大整数

    foobar[]是大小为b的计数数组

    N = sizeof(a), M = b 为常用符号,

    前两个循环:

    1. 将计数数组初始化为零O(M)
    2. 计算元素,比如a[]foobar[10] = 3O(N) 中是否有 3 个 '10'

    棘手的第三个循环:

    1. 外循环,毫无疑问,O(M)
    2. 内循环,你必须考虑总(最大)时间,j 可以增加:这是Sum(foobar[]) = sizeof(a) = N,所以确实这个循环,贯穿整个外循环循环迭代,势必最多执行N次。 所以两个循环整体是O(N+M),而不是直观的O(NM)

    所以总复杂度是:O(N) + O(M) + O(N+M) = O(N+M)

    如果您发现第三个循环的复杂性难以理解,请这样思考:

    这是一个 0 和游戏。如果有一些foobar[z] is large,那么有很多foobar[j] = 0,这几乎意味着跳过这样的i 的内部循环。否则,所有foobar[j] 的大小都差不多。

    很难分析i 的每次迭代,但很容易分析整个内部循环,因为我们知道foobar[] 的总和是一个常数。

    【讨论】:

      【解决方案2】:

      这看起来像 counting sort 实现。考虑到N(项目数)为数组a的长度,M(最大可能项目)为b,其时间复杂度为O(N+M)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-28
        • 1970-01-01
        • 2011-07-16
        • 1970-01-01
        • 2021-05-16
        • 1970-01-01
        相关资源
        最近更新 更多