【问题标题】:Changing O(n^3) to O(n^2) in JavaScript [duplicate]在 JavaScript 中将 O(n^3) 更改为 O(n^2) [重复]
【发布时间】:2017-11-14 11:35:03
【问题描述】:

我正试图在我的编码解决方案中节省时间。

我有一个名为tripletSum 的函数,它接受两个参数xa,其中x 是一个数字,a 是一个数组。

如果列表a包含三个元素加起来等于数字x,则该函数应该返回true,否则它应该返回false

我创建了以下工作解决方案:

function tripletSum(x, a) {
    for(var i = 0; i < a.length; i++) {
        for(var j = i + 1; j < a.length; j++) {
            for(var k = j + 1; k < a.length; k++) {
                if((a[i] + a[j] + a[k]) === x) {
                    return true;
                }
            }
        }
    }
    return false;
}

但这似乎不是最佳做法。如果我没记错的话,目前运行这个函数所需的时间是O(n^3),我认为它可以改进为O(n^2)的时间复杂度。

无论如何我可以更改此代码来做到这一点?

编辑:这不是另一个问题的重复,因为我要求对我当前在 JavaScript 中的示例进行特定改进,这不是它在标记的重复问题中所要求的。

【问题讨论】:

标签: javascript algorithm time-complexity


【解决方案1】:

为数组中包含的所有键保留一个类似字典的对象。然后在第二个循环中,从 x 中减去这两个值并在字典中查找该值。

function tripletSum(x, a) {
    var dictionary = {};
    for(var i = 0; i < a.length; i++) {
        dictionary[a[i]] = true;
    }

    for(var i = 0; i < a.length; i++) {
        for(var j = i + 1; j < a.length; j++) {
            var remainder = x - a[i] - a[j];
            if(dictionary[remainder])
                return true;
        }
    }
    return false;
}

【讨论】:

  • 我使用x = 5a = [2, 3, 1] 使用此解决方案运行了一个测试用例,它返回了false
  • 这会是预期的行为吗?该数组中唯一的三元组加起来为 6。
  • 对,对不起金发时刻......
【解决方案2】:

这里的想法是:您首先需要对数组a 进行排序。之后,您可以有一个循环遍历从 0 到 N - 2 的所有元素(仅)。让我们调用i 这个循环的索引。这就是数组已排序这一事实的用处。我们将使用数组已排序的知识来“挤压”“未处理”的子数组(范围从 i + 1 到第 N 个元素)。您现在将有 2 个值 leftrightleft 将指示未处理子数组的左侧索引,而right 将指示数组中未处理部分的右侧索引。一开始我们设置left = i + 1right = N - 1。我们计算suma[i] + a[left] + a[right]。现在我们有 3 个案例:

  1. If sum = x 然后返回 true
  2. 如果sum &gt; x,那么我们需要降低总和,所以我们需要将right减1(从右侧挤压)
  3. 如果sum &lt; x,那么我们需要使总和更大,所以我们需要将left 增加1(从左侧挤压)

以下是 Javascript 解决方案。

function tripletSum(x, a) {
    a.sort(function(i, j) {
        return i - j;
    });

    var N = a.length;

    for(var i = 0; i < N - 2; i++) {
        var left = i + 1, right = N - 1;

        while(left < right) {
            var sum = a[i] + a[left] + a[right];
            if(sum === x) {
                return true;
            }
            else if(sum > x) {
                right--;
            }
            else {
                left++;
            }
        }

    }

    return false;
}

时间复杂度为O(N^2),没有使用额外的空间。

【讨论】:

    【解决方案3】:

    您基本上可以利用二分查找和排序将复杂度从 O(n^3) 降低到 O(n^2*logn)。

    function tripletSum(x, a) {
        a.sort(function(a, b) {
                return a - b
            }) // O(n*logn)
        var n = a.length;
        for (var i = 0; i < n; i++) {
            for (var j = i + 1; j < n; j++) {
                if (a.indexOf(x - a[i] - a[j]) > j) {
                    return true; //O(n^2*logn)
                }
            }
        }
        return false;
    }
    
    console.log(tripletSum(0, [
        1,
        5,
        6,
        -2, 
        -3
    ]))

    总复杂度 = O(n*logn) + O(n^2*logn) ~ O(n^2*logn)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-29
      • 2012-11-22
      • 2013-10-20
      • 2014-06-13
      • 2021-12-22
      • 2019-12-23
      相关资源
      最近更新 更多