算法运行时复杂度:

时间:2018-02-01 16:01:38

标签: algorithm time-complexity

在careercup网站上,出现了这个问题(https://careercup.com/question?id=6270877443293184):

Given an array, find the number of tuples such that
A [i] + A [j] + A [k] = A [l] in an array, where i <j <k <l.

所提出的解决方案(下面)有效但状态运行时复杂度为O(n ^ 2)。在分析代码之后,我不认为它可以在少于n ^ 2 * log n的情况下完成。我的理由是它迭代遍历2d数组中的所有元素(n ^ 2并且它们在包含元组的列表中,检查每个元素,即O(n)。即使使用TreeMap并进行二进制搜索也可以只有减少是记录n,而不是常数时间。有人可以确认是否可以在O(n ^ 2)中完成并解释我的逻辑中有什么不正确吗?

建议的解决方案:

Fill 2 2d arrays with
arr1[i][j]=a[i]+a[j]
arr2[i][j]=a[j]-a[i]
j>i
In a map<int,list<int>>, map[arr1[i][j]].push_back(j)
For each element in arr2, search in the map.
Count all hits where j < k

2 个答案:

答案 0 :(得分:0)

你是对的,在最坏的情况下,这不是O(n^2)

作者显然认为来自list的{​​{1}}只包含少数成员;当我们声明哈希表的map<int,list<int>>操作的复杂性是find时,它就是我们使用的假设。回想一下,其冲突解析基于separate chaining的哈希表平均具有O(1)操作的恒定复杂度,但是当许多元素散列到相同的值时,它可以降级为线性复杂度。 / p>

实现方面,请注意,映射find需要是哈希表(即C ++中的map<int,list<int>>,Java中的std::unordered_map,而不是HashMap(或{{ 1)}在Java中)因为只有std::map TreeMap操作std::map find

答案 1 :(得分:0)

j中按升序排列map[arr1[][]]非常容易。

如果以递增的k顺序枚举arr2中的每个元素,则不必进行二分查找。您可以枚举所有j

因为您要增加k个订单,所以对于地图中的每个列表,您只需要记住您看到的最后一个列表。所以地图应该是map<int, <int, list<int>>>

由于您只触摸每个j一次,而且复杂度仅为O(n^2)