【问题标题】:which solution is better in terms of space.time complexity?就空间时间复杂度而言,哪种解决方案更好?
【发布时间】:2018-04-09 09:21:37
【问题描述】:

我有 2 个整数列表。他们都已经排序了。我想找到加起来等于给定数字的元素(每个列表中的一个)。

-第一个想法是遍历第一个列表并使用二进制搜索来查找与给定数字相加所需的数字。我知道这需要 nlogn 时间。

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

总体来说哪个更好?

【问题讨论】:

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


    【解决方案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.
    

    【讨论】:

    • 是的..2指针算法..你认为我应该在这里发布吗? @MBo
    • 误删:另外——还有O(1)内存的线性算法
    • @MBo.: 我也可以发布...但我避免了它,因为 OP 要求对这种分析采取一般方法..我会补充一点..感谢您指出
    • 是的,问题是关于一般方法,关于不确定条件下的合理选择,所以你关于权衡的答案非常完美。我不确定作者是否真的需要两指针算法,但值得一提。
    • @MBo.: 谢谢...我很乐意这样做
    【解决方案2】:

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

    1. 如果 A[a] + B[b] = T,记录该对,增加 a,然后重复。
    2. 否则,A[a] + B[b]
    3. 否则,A[a] + B[b] > T,递增 b,从 1 开始重复。
    4. 当然,如果 a 或 b 分别超过 A 或 B 的大小,则终止。

    例子:

    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
    

    上述算法将产生三对,但您可能需要九对。这可以通过检测这种情况来解决,为您看到的 A[a] 和 B[b] 的运行长度保留单独的计数器 ca 和 cb,并添加您添加的最后一对的 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).
    

    【讨论】:

      猜你喜欢
      • 2018-06-15
      • 1970-01-01
      • 1970-01-01
      • 2020-11-13
      • 1970-01-01
      • 2020-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多