C# - 生成数组中所有对的时间复杂度

时间:2018-04-06 10:46:47

标签: c# algorithm time-complexity

给定一组数字,生成所有唯一对。

例如,给定[ 1, 2, 3, 4, 5 ],唯一的数字对将是:

(1, 2), (1, 3), (1, 4), (1, 5)

(2, 3), (2, 4), (2, 5)

(3, 4), (3, 5)

(4, 5)

我的解决方案如下:

int[] numbers = new int[] { 1, 2, 3, 4, 5 };
HashSet<Pair> pairs = new HashSet<Pair>();

for(int i = 0; i < numbers.Length; i++)
{
    for(int j = i + 1, j < numbers.Length; j++)
    {
        pairs.Add(new Pair(numbers[i], numbers[j]));
    }
}

我认为时间复杂度看起来像O(n 2 - 1)减去1,因为j的迭代总是比i <1短< / em>的

对这类问题进行了一些研究之后,我找不到任何明确的答案,以确定是否可以更快地完成。有没有比O(n 2 -1)更好的解决方案?

4 个答案:

答案 0 :(得分:41)

思考问题的方法之一是解决问题的更快方法&#34;是为某些特定格式(你认为&#34;可能是最大/最难解决的#34;)来查看输出的大小。

如果输出为O(n^2),那么您无法比O(n^2)更快地解决问题,因为您必须为每个输出花费至少O(1)

你可以看到那里的模式,如果你有5个格式[1, 2, 3, 4, 5]的数字,那么唯一的一对

4 pairs in first row
3 pairs in second row
2 pairs...
1 pair

因为它们看起来像

(1, 2), (1, 3), (1, 4), (1, 5)

(2, 3), (2, 4), (2, 5)

(3, 4), (3, 5)

(4, 5)

如果数组中有20个变量(格式为[1, 2, 3,... 18, 19, 20]),则如下:

19 pairs
18 pairs
...
2 pairs
1 pair

因此输出大小为(n-1) + (n-2) + (n-3) ... + 3 + 2 + 1。你必须总结它(看看如何对系列求和),结果是O(n^2)

证实了什么?

最糟糕的情况是至少O(n^2)

另请注意,此时此刻,我们并不知道真正的最坏情况复杂性 - 算法可能更慢(我们只是发现某些输入需要O(n^2))。我们确信至少这些数据需要O(n^2)。对于不同的输入,它可以更快或更慢。

Conlusion :我们已经证明该算法至少花费O(n^2)时间(最坏情况),您创建的算法最多运行O(n^2)时间(如spyc post中所述)=你有最佳算法。

OP解决方案的额外信息: 使用HashSet检测冲突只是&#34; pseudoConstant&#34;并且仅适用于小数字和&#34;一些运气&#34;。大量数字需要O(n)。因此,您最终可以输入n^2输出,并且每个输出都需要n来处理,这会导致n^3复杂性。

您可以通过预处理任务来解决它:

1)对其进行排序 - 只需n log n,因此不会影响n^2

2)删除重复两次以上[1, 3, 3, 3, 5] -> [1, 3, 3, 5]的数字,O(n)

3)然后使用您的算法进行此更新:

3.1)在for i周期开始时:if (number[i] == number[i-1]) continue;

3.2)在for j周期开始时:记住最后一对。添加新对时,请查看最后一对并检查它是否相同。如果是这样 - continue;

示例:

Input: [1, 3, 3, 5]

1)i=0, j=1, number[0]=1, number[1]=3 -> add (1, 3)
2)i=0, j=2, number[0]=1, number[2]=3 -> same as last pair, use continue
3)i=0, j=3, number[0]=1, number[3]=5 -> add (1, 5)
4)i=1, j=2, number[1]=3, number[2]=3 -> add (3, 3)
5)i=1, j=3, number[1]=3, number[3]=5 -> add (3, 5)
6)i=2, before go to j-cycle, check number[i] === number[i-1] It is true, use continue

答案 1 :(得分:12)

如下:

first for loop - O(n)
    second for loop - O(n-1)

最佳时间复杂度:

enter image description here

  • 即使一次迭代可以忽略不计,您应该计算最坏情况的时间复杂度,enter image description here

您还可以使用二项式系数进行排列,以获得某个字符串的排列数。例如:

enter image description here

如果你有6个数字 {0,1,2,3,4,5} (n = 6),你想知道你可以做出多少种不同的排列,即:( 3,5),(5,3)等...然后(k = 2,每组两位数),排列量将是:

enter image description here 不同的排列,请注意虽然在这种情况下(3,5),(5,3)是单独计算的,所以它的顺序都很重要。如果您希望将(5,3)和(3,5)计为一个组合,则公式如下:

enter image description here

示例实现,计算排列!

static long factorial(long x) // calcs the factorial TimeCmplx = O(n)
{
    if (x == 1)
        return x;
    return x * factorial(x - 1);
}

static long permutations(long n , long k) //Check that (n , k) >= 0
{            
    // Permutations , n!/(n-k)!
    return factorial(n) / factorial(n - k);
}

答案 2 :(得分:5)

  

我认为时间复杂度看起来像O(n2 - 1)减去1,因为j的iteraton总是比i短1

如果它很重要(big-O-notation通常只会写出增长最快的术语),那么你会在[0,n]上迭代i,每个包含j超过[i + 1,n]的迭代所以迭代次数是(n∙(n-1))/ 2而不是n²-1。

此外,您的编辑更改为HashSet而不是列表更改最坏情况执行,但不是amortised value - 如果Pair.GetHashCode()始终返回相同的值,您已将其提升到O (n³),如在碰撞是常见的情况下,哈希集插入变为O(n)而不是常数。

答案 3 :(得分:0)

这是三角形算法的区域。

您有 N 输入,并且您希望输出三角形

您的输出三角形的高度 N-1 宽度 N-1 。< / p>

Area of a triangle = height * width / 2
                   = (N-1)  * (N-1) / 2
                   = (N^2 - 2N + 1) / 2

O(n^2 - n) 始终是最低/最佳算法费用!