【问题标题】:Algorithm for deciding if a,b,c exist in an array so that a+b+c = z? [duplicate]确定a,b,c是否存在于数组中的算法使得a + b + c = z? [复制]
【发布时间】:2018-04-17 18:59:15
【问题描述】:

为以下问题找到一个有效的算法有点困难。算法必须确定数组中是否有 3 个元素 a、b 和 c,以便 a+b+c 等于给定数字 z。

当然,天真的方法是尝试组合,但渐近所需的时间会太大。

在数组中查找 a 和 b 以使总和为 z 要容易得多。按升序对给定数组进行排序,如果 z-a 存在,则检查每个元素。但我不确定如何在 3 元素问题中实现它以及需要什么时间。

非常感谢任何帮助!

编辑:a、b、c 和 z 是整数。

【问题讨论】:

  • {a,b,c} 可以是负数吗?
  • 是的,只是规定所有元素都是整数。
  • 这是一个重复的任务吗,如果是的话,什么更可能改变,数组还是z?

标签: arrays algorithm sum element


【解决方案1】:

该方法非常类似于用 sum z 求 a 和 b。

首先对数组进行排序。然后在i 的位置修复a 并检查在限制i + 1 to n 中是否有sumz-a

由于您有一个 O(n) 算法来检查 z 是否与 ab 存在。我们只扩展它来修复 a 并检查是否可以使用另外两个变量来产生总和。给出O(n^2)的整体运行时间

来自here

// returns true if there is triplet with sum equal
// to 'sum' present in A[]. Also, prints the triplet
bool find3Numbers(int A[], int arr_size, int sum)
{
    int l, r;

    /* Sort the elements */
    sort(A, A+arr_size);

    /* Now fix the first element one by one and find the
       other two elements */
    for (int i=0; i<arr_size-2; i++)
    {

        // To find the other two elements, start two index
        // variables from two corners of the array and move
        // them toward each other
        l = i + 1; // index of the first element in the
                   // remaining elements
        r = arr_size-1; // index of the last element
        while (l < r)
        {
            if( A[i] + A[l] + A[r] == sum)
            {
                printf("Triplet is %d, %d, %d", A[i], 
                                         A[l], A[r]);
                return true;
            }
            else if (A[i] + A[l] + A[r] < sum)
                l++;
            else // A[i] + A[l] + A[r] > sum
                r--;
        }
    }

    // If we reach here, then no triplet was found
    return false;
}

【讨论】:

  • 非常感谢!非常完美。
【解决方案2】:

我想我应该写一个简短的评论作为答案,但我没有足够的声誉......所以这里什么都没有!


我现在能想到的最好的算法是 O(n^2),为了更好地解释这个算法,我们将从 O(n) 情况下的 a+b = z 开始(或者 O(nlgn) 如果它未排序)

首先,迭代 {a},并找到 {b} 使得 a+b = z。如果你天真地迭代所有 b 这将花费 O(n) 每个 {a},从而导致 O(n^2) 解决方案。但是,如果您越来越多地迭代 {a},则 {b} 的值必须严格递减。我们可以利用这些信息来降低时间复杂度,如下代码所示:

for a = first element, b = last element; a != last; a = next a
while ( ( b != first element ) and (a + b > z) )
      b = previous elemnet of b
if a + b == z
      return true

请注意,{b} 在整个循环中只遍历整个列表一次,因此它具有摊销 O(n) 的复杂性。


现在我们可以把这个原理应用到原来的问题上,我们可以遍历 {a},然后将这个 O(n) 算法应用到 {b, c} 以找到 {za},总复杂度是 O(n *n = n^2)。

希望有一个复杂度较低的解决方案,我不认为 O(n^2) 令人印象深刻,但我就是想不出更好的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-26
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-16
    • 1970-01-01
    • 2019-05-04
    相关资源
    最近更新 更多