问题是在一个由无符号整数组成的集合M中找到一对整数(a,b),其中a-b是n的倍数。给定一个小于集合M长度(M)的正整数n。下面是我写的代码片段。
我不太确定这个算法的时间复杂度是多少,而不是M的长度和n的值。在排除函数中,最坏情况是O(M)。然后它在m上的for循环中,然后是O(m²)另外,X初始化随n缩放,所以这里是O(n)总共是O(m^2) + O(n)忽略其他O(1)s。这是正确的吗?
同样,我应该取r = x % n
为O(1)吗?
欢迎任何与代码相关的建议!!大谢谢!
//array X is intialized of size n, all -1. Here the code is omitted.
for (int i = 0; i < m; i++)
{
if (currentLength > 1)
{
index = rand() % currentLength;
x = setM[index];
exclude(setM, index, ¤tLength);
r = x % n;
if (X[r] == -1)
{
X[r] = x;
}
else
{
printf("The pair: (%i, %i)n", X[r], x);
break;
}
}
else
{
break;
}
currentLength -= 1;
}
// to exclude an element based on index, then shift all elements behind by 1 slot
void exclude(int* array, int index, int* length_ptr)
{
if (index != *length_ptr - 1)
{
for (int i = index; i < *length_ptr - 1; i++)
{
array[i] = array[i + 1];
}
}
}
另外,我应该把
r = x % n
作为O(1)吗?
对,是0 (1)
我不太确定这个算法的时间复杂度…总共是O(m²)+ O(n)?
有点像但是还有更多的. 问题是m
和n
是不是独立的.
考虑n = 2
的情况,让m
增加。你的公式会给出O(m^2),但这是正确的吗?没有。因为% n
只有2个可能的结果(即0和1),所以循环for (int i = 0; i < m; i++)
只能运行3次才能得到匹配。无论你增加多少m
,循环都不会超过3个。在每个循环中,exclude
函数在最坏的情况下可能会移动到m
元素附近。一般来说,for (int i = 0; i < m; i++)
不能执行多于n+1
的循环。
所以对于m being larger than n
,你宁愿用O(n*m) + O(n)。当保持n
不变时,这就变成了O(m)。所以你的算法就是0 (m)关于m
。
现在考虑恒定的m
和增大的n
的情况。在这种情况下,公式是O(m²)+ O(n)因为m
是常数O(m^2)也是常数所以你的算法对于n
就是O(n)。
现在如果你增加m
和n
的公式是O(m^2) + O(n)但是由于m
和n
都增加了,所以O(m^2)最终会支配O(N),所以我们可以忽略O(N)。换句话说,你的算法对两者都是O(M^2)
回顾一下:
O(m) for constant n and increasing m
O(n) for constant m and increasing n
O(m^2) for increasing n and increasing m
欢迎任何与代码相关的建议
好吧,这个index = rand() % currentLength;
是只是一个坏主意!
您应该始终测试数组中的最后一个元素,即index = currentLength - 1;
为什么?简单地说,这将把exclude
变成0(1)。事实上,你甚至不需要它!当执行currentLength -= 1;
时,排除将自动发生。这个改变将提高像
这样的复杂性O(1) for constant n and increasing m
O(n) for constant m and increasing n
O(m)+O(n) for increasing n and increasing m
O(m)+O(n)可以表示为O(m)(或者O(n))。最重要的是它是线性的。
除此之外,你不需要currentLength
。将主循环改为
for (int i = m-1; i >= 0; --i)
,并使用i
作为index
。这将代码简化为:
for (int i = m-1; i >= 0; --i)
{
r = setM[i] % n;
if (X[r] == -1)
{
X[r] = setM[i];
}
else
{
printf("The pair: (%i, %i)n", X[r], setM[i]);
break;
}
}
您需要找到x%n==y%n
的两个数字x和y。它容易。使用一个键为x %n
的哈希表。从这一集合中添加其他数字,直到找到重复的数字。这是我们想要的一对。复杂度为0 (M)。