哪种解决方案在空间方面更好。时间复杂度?

时间:2017-10-27 17:36:51

标签: algorithm hashmap time-complexity hashtable memory-efficient

我有2个整数列表。它们都已经分类了。我想找到加起来给定数字的元素(每个列表中的一个)。

- 第一个想法是迭代第一个列表并使用二进制搜索来查找总和给定数字所需的数字。我知道这将花费nlogn时间。

另一个是将一个列表存储在哈希表/映射中(我真的不知道其中的区别)并迭代其他列表并查找所需的值。这需要一段时间吗?和n记忆?

整体哪个更好?

2 个答案:

答案 0 :(得分:1)

你正在比较它。但两者都有不同的方面。如果您有内存限制,散列不是一个好的选择。但如果你有足够的记忆,那么你可以负担得起。

此外,您将在计算机科学中多次看到时空权衡的概念。失去一些,总会有所收获。哈希在O(n)中运行,空间复杂度为O(n)。但是,如果仅搜索O(nlogn)时间复杂度,但空间复杂度为O(1)

长话短说,方案可让您决定选择哪一个。我只展示了一个方面。可以有很多。知道每个的约束和权衡,你就能够做出决定。

更好的解决方案:(时间复杂度:O(n)空间复杂度:O(1)

假设有2个数组ab。 现在WLOG假设a按升序排序,另一个按降序排序(即使不是这种情况,我们也可以相应地遍历它)。

  index1=0;index2=0; // considered  0 indexing
  while(index1 <= N1-1 && index2 <= N2-1)
  {
    if ((a[index1] + b[index2]) == x)
        // success
    else if ((a[index1] + b[index2]) > x)
        index2++;
    else
        index1++;
   }
   //failure no such element.

答案 1 :(得分:0)

按升序对列表A进行排序,按降序对列表B进行排序。设置a = 1且b = 1。

  1. 如果A [a] + B [b] = T,记录该对,增加a,然后重复。
  2. 否则,A [a] + B [b]&lt; T,增加a,并从1开始重复。
  3. 否则,A [a] + B [b]&gt; T,增量b,并从1开始重复。
  4. 当然,如果a或b分别超过A或B的大小,则终止。
  5. 示例:

    A = 1, 2, 2, 6, 8, 10, 11
    B = 9, 8, 4, 3, 1, 1
    T = 10
    
    a = 1, b = 1
    A[a] + B[b] = A[1] + B[1] = 10; record; a = a + 1 = 2; repeat.
    A[a] + B[b] = A[2] + B[1] = 11; b = b + 1 = 2; repeat.
    A[a] + B[b] = A[2] + B[2] = 10; record; a = a + 1 = 3; repeat.
    A[a] + B[b] = A[3] + B[2] = 10; record; a = a + 1 = 4; repeat.
    A[a] + B[b] = A[4] + B[2] = 14; b = b + 1 = 3; repeat.
    A[a] + B[b] = A[4] + B[3] = 10; record; a = a + 1 = 5; repeat.
    A[a] + B[b] = A[5] + B[3] = 12; b = b + 1 = 4; repeat.
    A[a] + B[b] = A[5] + B[4] = 11; b = b + 1 = 5; repeat.
    A[a] + B[b] = A[5] + B[5] = 9; a = a + 1 = 6; repeat.
    A[a] + B[b] = A[6] + B[5] = 11; b = b + 1 = 6; repeat.
    A[a] + B[b] = A[6] + B[6] = 11; b = b + 1 = 7; repeat.
    Terminate.
    

    如果没有按降序排序B,则可以在没有额外空格的情况下执行此操作,设置b = | B |并递减它而不是增加它,有效地向后读它。

    上述程序错过了一些重复的答案,其中B有一串重复的值,例如:

    A = 2, 2, 2
    B = 8, 8, 8
    

    如上所述的算法将产生三对,但您可能需要九对。这可以通过检测这种情况来解决,保持单独的计数器ca和cb表示你看到的A [a]和B [b]的运行长度,并添加你添加的最后一对的ca * cb - ca副本袋子。在这个例子中:

    A = 2, 2, 2
    B = 8, 8, 8
    a = 1, b = 1
    ca = 0, cb = 0
    A[a] + B[b] = 10; record pair, a = a + 1 = 2, ca = ca + 1 = 2, repeat.
    A[a] + B[b] = 10; record pair, a = a + 1 = 3, ca = ca + 1 = 2, repeat.
    A[a] + B[b] = 10; record pair, a = a + 1 = 4;
                      a exceeds bounds, value of A[a] changed;
                      increment b to count run of B's;
                      b = b + 1 = 2, cb = cb + 1 = 2
                      b = b + 1 = 3, cb = cb + 1 = 3
                      b = b + 1 = 4;
                      b exceeds bounds, value of B[b] changed;
                      add ca * cb - ca = 3 * 3 - 3 = 6 copies of pair (2, 8).