【问题标题】:Maximum Distance in Arrays | Competitive coding question数组中的最大距离 |竞争性编码问题
【发布时间】:2020-10-03 18:04:22
【问题描述】:

问题陈述-

给定 m 个数组,每个数组按升序排序。现在你可以从两个不同的数组中取出两个整数(每个数组选择一个)并计算距离。我们将两个整数 a 和 b 之间的距离定义为它们的绝对差 |a-b|。你的任务是找到最大距离。

例子-

Input: 
[[1,2,3],
 [4,5],
 [1,2,3]]
Output: 4

我的方法 - 由于数组已排序,因此在最终答案中,一个元素将来自数组的第一个索引,而另一个元素将来自数组的最后一个索引。因此,我能够设计一个蛮力解决方案,以得到答案。基本上我正在生成一个数组的最后一个元素和另一个数组的第一个元素的所有可能组合。这给了我 O(n^2) 的 TC。 我怎样才能优化我的方法。 ?

【问题讨论】:

    标签: algorithm data-structures


    【解决方案1】:

    这很简单。

    • 维护所有列表中具有最小值的最小变量。
    • 包括当前最小值之前,计算当前最小值与当前列表最大值的差异。
    • 从第一个到最后一个,从最后一个到第一个执行第 2 步。
    • 通过这种方式,您将考虑最小值和最大值的所有可能性,而无需为每个可能性生成或计算。

    片段:

    public int maxDistance(List<List<Integer>> arrays) {
            int max_diff = 0,min = arrays.get(0).get(0);
            
            for(int i=1;i<arrays.size();++i){
                List<Integer> curr = arrays.get(i);
                max_diff = Math.max(max_diff,Math.abs(curr.get(curr.size()-1) - min));
                min = Math.min(min,curr.get(0)); // take min afterwards
            }
            
            min = arrays.get(arrays.size()-1).get(0);
            
            for(int i=arrays.size()-2;i>=0;--i){
                List<Integer> curr = arrays.get(i);
                max_diff = Math.max(max_diff,Math.abs(curr.get(curr.size()-1) - min));
                min = Math.min(min,curr.get(0));  // take min afterwards
            }
            
            return max_diff;
        }
    
    • 时间复杂度:O(n),空间复杂度:O(1)。

    【讨论】:

    • 有趣!,需要添加一个条件,即其他值(最大值)不应该来自同一个列表
    • @shaileshbhagat,用斜体强调的算法部分确保导致差异的值不会来自同一个列表。
    • @shaileshbhagat 同意 trincot。
    【解决方案2】:

    正如您正确观察到的,只有数组的最小和最大元素是有意义的。你可以在O(n)中找到n排序数组的最小值,在O(n)中找到最大值,答案似乎是max - min,也就是O(1)

    如果我们不允许 max 和 min 属于 same 数组,问题就更难了。在这种情况下,蛮力解决方案(考虑所有最小-最大组合)将再次需要O(n^2) 计算。但你可以做得更好:

    • 构建一个二维数组m 使得m[i][0] = min(array[i])m[i][1] = i;对它进行升序排序,以便m[j][0] &lt;= m[j+1][0](成本:O(n log n)

    • 使用M[i][0] = max(array[i])m[i][1] = i 构建另一个二维数组M;降序排序,以便m[j][0] &gt;= m[j+1][0](成本:O(n log n)

    • 检查是否m[0][1] != M[0][1],

      • 如果为真,则可以安全返回是M[0][0] - m[0][0]
      • 否则,结果将为max(M[0][0] - m[1][0], M[1][0] - m[0][0])

    您可以通过跟踪最大、第二大、最小和第二小的元素以及它们的数组索引来避免对 mM 进行完全排序(提高了 O(n) 的成本) -但是在竞赛中编程时,足够简单和最佳通常比真正最佳但难以编写更好。

    【讨论】:

      【解决方案3】:

      你可以在线性时间内做到这一点:

      • 找出总体上两个值最少的两个数组。为此,您需要扫描所有输入数组的第一个值。我们将这两个数组称为 A 和 B,其中 A[0]

      • 找出两个值最大的两个数组。为此,您需要扫描所有输入数组的最后一个值。我们将这两个数组称为 C 和 D,其中 C[last] >= D[last] 和 D[last] >= all X[last],其中 X != C

      • 如果 A != C,则返回 C[last] - A[0]

      • 否则,以下两个表达式中最大的一个:D[last] - A[0] 和 C[last] - B[0]

      在 JavaScript 中的实现:

      function solve(arrays) {
          if (arrays.length < 2) throw "must have at least 2 arrays";
          let a, b, c, d;
          for (let row of arrays) { // collect two least and two greatest
              let low = row[0], high = row[row.length-1];
              if (!a || low < a[0]) [a, b] = [row, a];
              else if (!b || low < b[0]) b = row;
              if (!c || high > c[c.length-1]) [c, d] = [row, c];
              else if (!d || high > d[d.length-1]) d = row;
          }
          return a !== c ? c[c.length-1] - a[0]
                : Math.max(c[c.length-1] - b[0],
                           d[d.length-1] - a[0]);
      }
      
      let res = solve([[1,2,3],[4,5],[1,2,3]]);
      console.log(res);  // 4

      【讨论】:

        猜你喜欢
        • 2021-09-15
        • 2023-03-08
        • 1970-01-01
        • 2023-01-30
        • 2021-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-15
        相关资源
        最近更新 更多