在书Introduction to the Design & Analysis of Algorithms中,针对元素唯一性问题提出了以下解决方案:
ALGORITHM UniqueElements(A[0 .. n-1])
// Determines whether all the elements in a given array are distinct
// Input: An array A[0 .. n-1]
// Output: Returns "true" if all the elements in A are distinct
// and false otherwise.
for i := 0 to n - 2 do
for j := i + 1 to n - 1 do
if A[i] = A[j] return false
return true
如何计算此算法的平均成本(即给定n的比较次数)?关于输入的合理假设是什么?
答案 0 :(得分:1)
如果您对输入一无所知,那么合理的假设是它是随机的。如果是这样,并且如果可能选择的空间很大(例如,所有实数的集合),则两个元素相同的可能性很小。 (数学上,我们说两个随机选择的实数不同的事件是 almost sure 。)
这意味着您的平均情况等于最坏情况:您必须扫描数组中的每个元素以确保每个元素都是不同的。然后,比较次数为n * (n - 1) / 2
,或1 ... n
的总和。
答案 1 :(得分:0)
由于您以嵌套方式在数组上迭代两次,因此最坏情况下的成本应为O(n²)..
仔细观察会告诉您,因为您在检查之后从元素开始第二次循环,所以:
N-1 + (N-2) + (N-3) + (N-4) + (N-5) + .... + 1
比较,因此确切的平均费用为N*(N-1) / 2
根据你的评论,我认为你应该假设在可能的值集之间选择了每个元素。
这意味着元素A[i]
的概率1/n
恰好是指定值。从这里开始,您可以考虑以下事项:
A[i]
中的任何元素。拥有A[i] == A[i+1]
的概率是多少?它是1/n²
,因为两个元素都应该是随机的。A[i] == A[i+2]
的概率是多少?你有1/n * (n-1/n) * 1/n
,因为你分别有一个指定的元素,除了指定的元素以外的任何东西,以及相同的指定元素A[k]
扩展任何元素k>i
的论证,然后添加所有概率,您将拥有从指定的一个开始在阵列中拥有两个唯一元素的平均概率A[i]
i = 0..l-1
开始,您可以进一步扩展。当然,每个不同的i
都会有不同的概率,因为随着i
的增加,数组会更短。 注意:n
是可以插入数组的不同项目的数量,而不是其长度。
在此之后,您可以轻松估算平均比较成本..
答案 2 :(得分:0)
如果您需要给定输入长度的精确值,那么这将起作用(认为它是过度杀伤):
ALGORITHM complexity_counter_of_UniqueElements(A[0 .. n-1])
// Determines whether all the elements in a given array are distinct
// Input: An array A[0 .. n-1]
// Output: Returns "true" if all the elements in A are distinct
// and false otherwise.
counter acc = 0;
for i := 0 to n - 2 do
for j := i + 1 to n - 1 do
//if A[i] = A[j] return false
acc := 1 + acc
return acc
很容易看出这个算法是O(n n),这可能是你感兴趣的。算法将每个元素与每个其他元素进行比较。如果您创建了一个包含此结果的表,则该表必须至少((n n)/ 2)才能保存所有结果。
修改强> 我现在看到你真正要问的是什么。
您需要计算每次比较可能导致匹配的概率。这取决于元素的大小(生活在A中的东西)以及它们具有什么样的分布。
假设随机分布任意两个随机A [x] == A [y],其中x!= y的概率为1.0 /(元素的可能值的数量)。
P(n)
total_chance := 0.0
for i:= 0 to n - 2 do
for j := i + 1 to n - 1 do
this_chance := 1.0/(number_of_possible_values_of_element)
total_chance := total_chance + ((1-total_chance)*this_chance)
// This should be the the probability of the newly compared pair being equal weighted
// to account for the chance that it actually mattered (ie, hadn't found a match earlier)
return total_chance
O((1-P(n)) n n),但P(n)<&lt; = 1,因此它小于n * n
答案 3 :(得分:0)
我认为很难谈论平均成本。最坏的情况是成本为O(n 2 )并且当重复的元素朝向数组的末尾时发生,例如:
2 3 4 5 ... 1 1
或者当数组只包含不同的元素时。
最好的情况是数组以两个重复元素开头,如下所示:
1 1 ...
在这种情况下,成本是单一比较。另一个好例子是当数组开头附近有一个元素在数组末尾重复时,如下所示:
2 3 4 1 ... 1
这将是(更接近)O(n)。
事实是成本取决于输入,所以你可能会假设你总是遇到最坏的情况并试图找到一个更好的算法,可能是基于对数组进行排序或使用哈希表的东西,给你O(nlog n)最坏情况和O(n)平均情况。