【问题标题】:Big O - is n always the size of the input?大 O - n 总是输入的大小吗?
【发布时间】:2016-01-11 22:43:08
【问题描述】:

我自己编了一个面试式的问题,并对我的解决方案的大 O 提出了一个问题。我将在下面说明问题和我的解决方案,但首先让我说明显的解决方案涉及嵌套循环并且是 O(n2)。我相信我找到了一个 O(n) 解决方案,但后来我意识到它不仅取决于输入的大小,还取决于输入的最大值。看来我的 O(n) 运行时间只是技术性的,它可以轻松运行在 O(n2) 时间或者在现实生活中更糟。

问题是: 对于给定正整数数组中的每一项,打印数组中所有其他项的倍数。

示例输入:

[2 9 6 8 3]

示例输出:

2: 6 8
9:
6:
8:
3: 9 6

我的解决方案(在 C# 中):

private static void PrintAllDivisibleBy(int[] arr)
{
    Dictionary<int, bool> dic = new Dictionary<int, bool>();
    if (arr == null || arr.Length < 2)
        return;

    int max = arr[0];
    for(int i=0; i<arr.Length; i++)
    {
        if (arr[i] > max)
            max = arr[i];
        dic[arr[i]] = true;
    }

    for(int i=0; i<arr.Length; i++)
    {
        Console.Write("{0}: ", arr[i]);
        int multiplier = 2;
        while(true)
        {
            int product = multiplier * arr[i];
            if (dic.ContainsKey(product))
                Console.Write("{0} ", product);

            if (product >= max)
                break;
            multiplier++;
        }
        Console.WriteLine();
    }
}

因此,如果数组项中有 2 个是 1 和 n,其中 n 是数组长度,则内部 while 循环将运行 n 次,这相当于O(n2)。但是,由于性能取决于输入值的大小,而不是列表的长度,所以它是 O(n),对吧?

您认为这是一个真正的 O(n) 解决方案吗?由于技术原因,它只是 O(n),但在现实生活中速度较慢吗?

【问题讨论】:

  • 我看不出有任何击败O(n^2)的方法,而且排序似乎也没有帮助。

标签: algorithm integer big-o


【解决方案1】:

好问题!答案是,不,n 并不总是输入的大小:你不能真的在不定义 n 的含义的情况下谈论 O(n),但人们通常使用不精确语言并暗示n 是“在这里扩展的最明显的东西”。从技术上讲,我们通常应该说诸如“这种排序算法在列表中的元素数量中执行一些比较 O(n)”:具体说明 n 是什么,以及我们正在测量的数量(比较) .

如果你有一个算法依赖于两个不同事物的乘积(这里是列表的长度和其中最大的元素),正确的表达方式是O(m*n),然后定义mn 适用于您的上下文。因此,我们可以说您的算法执行O(m*n) 乘法,其中m 是列表的长度,n 是列表中最大的项目。

【讨论】:

  • N是数组的大小,他想知道回答这个问题需要多少次N。
  • 我同意。发帖人在这里使用n 表示两个不同的东西,这就是混乱的根源。
【解决方案2】:

当您必须迭代 n 个元素并在每次迭代中执行一些恒定时间操作时,算法是 O(n)。算法的内部 while 循环不是恒定时间,因为它取决于数组中最大数字的巨大程度。

您的算法的最佳情况运行时间是 O(n)。这是当所有 n 个数字都相同时的情况。

您的算法的最坏情况运行时间为 O(k*n),其中 k = 您的机器上可能的 int 的最大值如果您真的坚持为 k 的值设置上限。对于 32 位 int,最大值为 2,147,483,647。你可以说这个 k 是一个常数,但是这个常数显然是

  • 对于输入数组的每种情况都不是固定的;并且,
  • 不可忽略。

【讨论】:

    【解决方案3】:

    您认为这是一个真正的 O(n) 解决方案吗?

    运行时实际上是O(nm),其中marr 中的最大元素。如果您的数组中的元素由一个常数限定,您可以将算法视为O(n)

    你能改进运行时间吗?这是您可以做的其他事情。首先请注意,您可以确保元素是不同的。 (您在 hashmap 中压缩数组,该数组存储在数组中找到元素的次数)。那么您的运行时将是max/a[0]+max/a[1]+max/a[2]+...&lt;= max+max/2+...max/max = O(max log (max))(假设您的数组 arr 已排序)。如果将其与显而易见的 O(n^2) 算法相结合,您将得到 O(min(n^2, max*log(max)) 算法。

    【讨论】:

      猜你喜欢
      • 2022-07-22
      • 2021-02-16
      • 1970-01-01
      • 1970-01-01
      • 2020-09-24
      • 1970-01-01
      • 2019-10-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多