【问题标题】:Find two elements in an array that sum to k [duplicate]在数组中找到两个总和为k的元素[重复]
【发布时间】:2011-08-03 13:47:39
【问题描述】:

可能重复:
Given two arrays a and b .Find all pairs of elements (a1,b1) such that a1 belongs to Array A and b1 belongs to Array B whose sum a1+b1 = k .

给定:一个未排序的整数数组A
输入:整数k

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

例子:

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

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

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

【问题讨论】:

  • 你是如何得到输出对{3,3}的?输入数组中只有一个 3。
  • 是否允许否定元素?
  • 您的数组 A 中只有一个值 3。{3,3} 仍然是解决方案集的一部分吗?
  • 不允许使用负数@Ben Voigt。

标签: c++ arrays algorithm


【解决方案1】:

有 k 对整数的总和为 k:{0,k}, {1,k-1}, ... 等等。创建一个大小为 k+1 的数组 B,其中元素为布尔值。对于数组 A 的每个元素 e,如果 e

【讨论】:

    【解决方案2】:

    一个可以减少的,

    元素唯一性位,

    到这个。没有 O(n)。

    【讨论】:

    • 你能暗示一下你的意思吗?或者链接到元素唯一性位的定义和减少?
    【解决方案3】:

    http://codepad.org/QR9ptUwR

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

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

    【讨论】:

    • std::map<>::insert(x) 是 O(log N),std::map<>::count(x) 是 O(N)。你的算法不是 O(N^2) 吗?
    • @Rob Adams,我猜,map 中的计数是 O(logN),因为它不包含具有相同键的多个元素。多图中的计数为 O(N)。我上面的算法是 O(NlogN)。如果我们使用 hashmap 而不是 map,我们将有 O(N) 算法。
    • 从 C++11 开始,我们会这样做:unordered_map
    • 为什么不在这里发布代码 ;-)
    【解决方案4】:

    我只是想出了一个简单的算法:

    • 创建一个位域,表示从 0 到 k 的数字,标记为 B
    • 对于 A 中的每个数字 i
      • 设置 B[i]
      • 如果设置了 B[k-i],则将 (i, k-i) 添加到输出中

    现在正如人们提出的那样,如果您需要有两个数字 3 的实例来输出 (3, 3),那么您只需切换上述算法中最后两个语句的顺序即可。

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

    【讨论】:

    • 您的算法需要时间 O(k*n),其中 k 是目标数。这比 O(n) 要糟糕得多。
    • 不,它是 O(n),其中 n 由 A 的长度确定。位域是恒定时间查找 O(1),而不是您正在考虑的线性时间查找 O(n) .
    • 是的,你是对的。我误读了您的算法,并假设您正在阅读 B 中的每个插槽。
    • 这个算法需要 O(k) 空间并且等效于建议的 (java) 哈希集解决方案(在 c++ 中集合是一棵树)
    • 我想你可能会感到困惑,蒂姆,我不使用集合数据结构。我使用一个 k 大小的位域,所以从 0 到 k 的每个数字都是 1 位,因此如果你想学究气,它使用 O( ceil( k / 8 ) ) 字节。
    【解决方案5】:

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

    【讨论】:

    • 从技术上讲,没有完美的散列函数,散列表仅摊销时间 O(1)。尽管仍然是一个聪明的解决方案。但是,如果3 是否可以使用两次的问题是,那么您必须在哈希构造期间计算每个成员。
    • 根据问题,空间根本没有界限,但这是 C++,其中整数通常是有界的,所以你有一个完美的散列函数 - 恒等式功能。您只需要一个巨大的哈希表(实际上是查找表),这需要非常大的 - 但常量 - 初始化时间!多田! ;) 这证明了复杂性分析可能会产生误导,尤其是当您假设内存无限时。
    • @Robin 哈希与恒等函数的不同之处在于它确实与输入数量呈线性关系。恒等函数仅限于整数,所需时间与最小和最大元素之间的间隔一样多;它绝不是“线性的”。
    • @bdares 正确优化后,标识函数根本不需要任何时间;它什么也没做。
    • @Robin:无限空间与无限初始化空间不同。如何在恒定时间内初始化无限空间哈希表?我很确定无限空间 Debanjan 意味着您可以分配额外的数组等。使用 O(n^2) 空间将需要 O(n^2) 时间,这不是众所周知的事实吗?所以我真的看不出你的论点有任何可信度。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-14
    • 2012-08-04
    • 2016-05-14
    • 2013-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多