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