Algorithm 大O-n总是输入的大小吗?

Algorithm 大O-n总是输入的大小吗?,algorithm,integer,big-o,Algorithm,Integer,Big O,我自己编了一个面试风格的问题,并对我的解决方案中的大O提出了一个问题。我将在下面陈述这个问题和我的解决方案,但首先让我说,显而易见的解决方案涉及一个嵌套循环,是O(n2)。我相信我找到了一个O(n)解,但后来我意识到它不仅取决于输入的大小,还取决于输入的最大值。看起来我的O(n)的运行时间只是一个技术问题,在现实生活中,它很容易在O(n2)时间内运行,甚至更糟 问题是: 对于给定正整数数组中的每个项目,打印数组中所有其他项目,这些项目是当前项目的倍数 输入示例: [2 9 6 8 3] 示例输

我自己编了一个面试风格的问题,并对我的解决方案中的大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 dic=新字典();
如果(arr==null | | arr.Length<2)
返回;
int max=arr[0];
对于(int i=0;i max)
max=arr[i];
dic[arr[i]]=真;
}
对于(int i=0;i=max)
打破
乘法器++;
}
Console.WriteLine();
}
}
因此,如果数组项中有2个是1和n,其中n是数组长度,则内部while循环将运行n次,这相当于O(n2)。但是,因为性能取决于输入值的大小,而不是列表的长度,所以它是O(n),对吗


你认为这是一个真正的O(n)解吗?这仅仅是因为技术上的原因,但在现实生活中速度较慢吗?

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

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

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

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

你的算法最坏的运行时间是O(k*n),其中k=如果你真的坚持给k的值加上一个上限,那么在你的机器上int的最大值。对于32位int,最大值为。你可以说k是一个常数,但这个常数显然是

  • 对于输入数组的每种情况都不固定;以及
  • 不可忽视
你认为这是一个真正的O(n)解吗?< /P> 运行时实际上是
O(nm)
,其中
m
arr
中的最大元素。如果数组中的元素以常数为界,则可以考虑算法为“代码> o(n)< /代码>


你能改进运行时间吗?这是你还能做的。首先请注意,您可以确保元素是不同的。(在hashmap中压缩数组,其中存储在数组中找到元素的次数)。那么您的运行时将是
max/a[0]+max/a[1]+max/a[2]+…我看不出任何方法可以击败
O(n^2)
,排序似乎也没有帮助。n是数组的大小,他想知道回答这个问题需要n的多少倍。我同意。海报在这里用
n
来表示两种不同的东西,这就是混乱的根源。
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();
    }
}