C++ 在数组中查找两个和为k的元素

C++ 在数组中查找两个和为k的元素,c++,arrays,algorithm,C++,Arrays,Algorithm,可能重复: 给定:未排序的整数数组A 输入:整数k 输出:所有两个元素集,每个元素集的元素总和等于O(n)中的k 例如: A={3,4,5,1,4,2} 输入:6 输出:{3,3},{5,1},{4,2} 注意:我知道一个O(nlogn)解决方案,但这需要对数组进行排序。有没有办法用O(n)来解决这个问题。一个非平凡的C++数据结构可以使用,即没有绑定空间,使一个常数时间查找表(哈希),这样你就可以看到一个特定的整数是否包含在数组中(O(n))。然后,对于数组中的每个元素,查看是否包含k-A[

可能重复:

给定:未排序的整数数组
A

输入:整数
k

输出:所有两个元素集,每个元素集的元素总和等于O(n)中的
k

例如:

A={3,4,5,1,4,2}

输入:6
输出:
{3,3},{5,1},{4,2}


注意:我知道一个O(nlogn)解决方案,但这需要对数组进行排序。有没有办法用O(n)来解决这个问题。一个非平凡的C++数据结构可以使用,即没有绑定空间

,使一个常数时间查找表(哈希),这样你就可以看到一个特定的整数是否包含在数组中(O(n))。然后,对于数组中的每个元素,查看是否包含
k-A[i]
。对于每个元素,这需要恒定的时间,因此总共需要O(n)个时间。这假设元素是不同的;使它与重复的元素一起工作并不困难。

有k对整数求和到k:{0,k},{1,k-1}。。。等等。创建一个大小为k+1的数组B,其中元素为布尔值。对于数组A的每个元素e,如果e只是我脑海中的一个简单算法:

  • 创建一个表示从0到k的数字的位字段,标记为B
  • 对于A中的每个数字i
    • 集合B[i]
    • 如果设置了B[k-i],则将(i,k-i)添加到输出中
现在,正如人们所提出的,如果需要输出数字3的两个实例(3,3),那么只需在上述算法中切换最后两个语句的顺序

另外,我确信这个算法有一个名字,或者至少有更好的名字,所以如果有人知道我会很感激你的评论。

这将打印所有对。该算法与上面@bdares所述的相同

我使用了stl映射,因为我们在stl中没有哈希表。

可以减少

元素唯一性位


对这个。否O(n)。

您如何导出输出对
{3,3}
?输入数组中只有一个3。是否允许使用负元素?数组A中只有一个值3。{3,3}是否仍然是解决方案集的一部分?Ben Voigt不允许使用负数。您的算法需要时间O(k*n),其中k是目标数。这比O(n)糟糕得多。不,是O(n),其中n由A的长度决定。位域是一个常数时间查找O(1)而不是你所想的线性时间查找O(n)。是的,你是对的。我误读了你的算法,假设你在B中读取每个时隙。这个ALGO需要O(k)空间,相当于所提议的(java)哈什特解决方案(C++集合是一棵树)。我想你可能会迷惑提姆,我不使用一个集合数据结构。我使用一个k大小的位字段,因此从0到k的每个数字都有1位,因此如果你想学究的话,它使用
O(ceil(k/8))
字节。
std::map::insert(x)
是O(logn),而
std::map::count(x)
是O(N)。你们的算法不是这样O(N^2)吗?@Rob Adams,我猜,地图中的计数是O(logN),因为它不包含具有相同键的多个元素。多重映射中的计数为O(N)。我上面的算法是O(NlogN)。如果我们使用hashmap而不是map,我们将有O(N)算法从技术上讲,缺少一个完美的散列函数,一个散列表只是摊销时间O(1)。尽管这是一个聪明的解决方案。但是,如果代码< 3 > /Cube >是否可以使用两次,那么在哈希构造中,你必须对每个成员进行计数。根据这个问题,根本没有绑定空间,但这是C++,其中整数通常是有界的,因此你有一个完美的哈希函数-身份函数。您只需要一个超大的哈希表(实际上是查找表),它需要非常大但恒定的初始化时间!多田!;)这证明了复杂性分析可能会产生误导,特别是当你假设无限内存时。散列函数不同于身份函数,因为它确实与输入的数量成线性关系。恒等式函数仅限于整数,所需时间与最小和最大元素之间的间隔相同;它在任何意义上都不是“线性的”。@b当适当优化时,标识函数根本不需要任何时间;它什么都不做。@Robin:无限空间与无限初始化空间不同。如何在固定时间内初始化无限空间哈希表?我很确定,Debanjan所说的无界空间意味着可以分配额外的数组等。使用O(n^2)空间不是需要O(n^2)时间吗?所以我看不出你的论点有什么可信度。你能给我一些暗示吗?或者链接到元素唯一性位的定义和归约?