Performance 在3个数组中搜索公共数的复杂性

Performance 在3个数组中搜索公共数的复杂性,performance,algorithm,Performance,Algorithm,有三个数组a1、a2、a3,大小为n。函数在这些数组中搜索公共编号。 算法是下一个: foreach n in a1 if n is found in a2 if n is found in a3 return true return false 我猜更糟的情况将是下一个:a1和a2相等,a3不包含任何与a1相同的数字 迭代数组a1的复杂度为O(i)。 搜索数组a2或a3的复杂度为f(n)(我们不知道如何搜索它们)。 我猜想,更糟情况下的总体复

有三个数组a1、a2、a3,大小为n。函数在这些数组中搜索公共编号。 算法是下一个:

foreach n in a1
    if n is found in a2
        if n is found in a3
            return true

return false
我猜更糟的情况将是下一个:a1和a2相等,a3不包含任何与a1相同的数字

迭代数组a1的复杂度为O(i)。 搜索数组a2或a3的复杂度为f(n)(我们不知道如何搜索它们)。 我猜想,更糟情况下的总体复杂性将是:

O(n)=n*f(n)*f(n)=n*(f(n))^2

有人告诉我这是错误的。
那么什么是正确答案呢?

我认为最糟糕的复杂性是n.log n。您可以对每个数组进行排序,然后进行比较。

这里需要注意的重要一点是“is found”函数的运行时间是多少

有两种可能的答案:

案例1:如果a2列表和a3列表已排序, 然后这个函数是logn时间二进制搜索,所以你得到N*logn(N)^2

案例2:如果列表无序,
然后每个搜索将花费n个时间(其中n是每个列表的长度)。。。因此,对于给定的算法,它将是n*n*n=n^3

对于每个项目(n),您正在通过另外两个数组(2f(n))循环。。所以它是n*2f(n)=o(n*f(n))

顺便说一句,最好的方法是:
保留在第一个数组中找到的项目的数组或散列。
然后检查其他两个数组,看看它们是否有已找到的项

将项保存在数组或哈希中,查找为O(1)。
你只是在3个数组中循环一次,所以你的复杂度是O(max{n,f(n)})

好吧,快速的答案是O(n^3),假设它们都有相同的长度。最糟糕的情况是,我们在a2中的最后一个位置找到了我们要查找的元素,因此我们将跨越整个数组,a3中也一样,或者它在a3中不存在。这对于a1中的所有元素都是一样的,我们必须一直跨越3个数组,假设每个数组的长度为n,那么总的复杂度为n^3

n * f(n) * f(n) = n * (f(n))^2 
有人告诉我这是错误的。那么正确答案是什么

给定算法的正确答案为:

n * (f(n) + f(n)) = O(n*f(n))

对于
a1
中的每个
n
,您不需要搜索
a3
数组
f(n)
次,因此您应该使用
+
而不是
*
a2
的元素放入一个集合
s2
中,将
a3
的元素放入一个集合
s3
。这两种操作在每个数组的元素数量上都是线性的。然后,迭代
a1
并检查元素是否位于
s2
s3
中。查找是固定时间的。因此,整个算法的最佳可实现复杂度为:

O(n1 + n2 + n3)

其中
n1
a1
的元素数,依此类推
n2
n3
。换句话说,该算法在元素数量上是线性的。

因此在您描述的最坏情况下,
a1
a2
是相等的,并且
a3
不包含任何与其他元素相同的数字,那么对于
a1
中的每个
n
,您将搜索
a2
a3

因此,运行时间似乎与
2n^2
成正比。也就是说,这与写作是一样的:

int jcnt, kcnt;
for (int i = 0; i < n; ++i)
{
    for (int j = 0; j < n; ++j)
    {
        ++jcnt;
    }
    for (int k = 0; k < n; ++k)
    {
        ++kcnt;
    }
}
int total = jcnt+kcnt;
intjcnt,kcnt;
对于(int i=0;i
您会发现,
total
将等于
2n^2


当然,假设数组是无序的。如果订购了
a2
a3
,并且您可以进行二进制搜索,那么它将是
2n(logn)

,最坏的情况是
3*n
。他只搜索一项。@JimMischel我们有3个循环,第一个循环跨越a1,第二个和第三个循环分别在a2和a3中搜索,所以我们有3个循环,每个循环可以从1到n,所以它是n^3而不是3*n。如果在a2中找到n,意味着我们将在a2中搜索n,这可能需要多达n个比较。这些循环如何不嵌套?如果条件在foreach循环内,则找到的“运算符”是一个函数,用于在数组中搜索该元素,因此它们是嵌套的。是的,循环是嵌套的。但是嵌套只有一个层次,所以是2n^2,而不是n^3。他没有要求更快或更好的算法,他想知道给定算法的复杂度,有很多不同的方法可以解决这个问题。好吧,有时候人们需要的不是他们要求的:)如果每次都在a2中找到呢?然后我们将在a3中搜索它,我们应该以最坏的为目标case@AkramMellice:如果每次都在a2中找到:
(f(n)+f(n))=2*f(n)=O(f(n))
常量因子不包括在大O符号中。这个问题本身突出了完全依赖大O的问题之一,因为它不包括常量因子,对于一个小数据样本,
O(n^4)
可能比
O(n)
快,如果它真的是
K*O(n)
,其中
K
是一个非常大的常数(
K>=n^3
),我相信这就是他们在这个面试问题中真正测试你知识的地方。