【问题标题】:Nested List weight sum javascript嵌套列表权重总和 javascript
【发布时间】:2019-02-08 00:52:39
【问题描述】:

我正在尝试解决这个问题,我们计算给定数字数组的嵌套权重总和。

给定一个嵌套的整数列表,返回其中所有整数的总和 按深度加权的列表。

例如:

[[1,1],2,[1,1]] ====> 解是 10。

深度 2 有四个 1,深度 1 有一个 2。

这是我写的代码:

var depthSum = function (nestedList, sum=0, depth=1) {
    for(let i=0; i<nestedList.length; i++){
        let val = nestedList[i];
        if (Array.isArray(val)) {
            return depthSum(val, sum, depth+1);
        } else {
            sum += val * depth;
        }
    };
    return sum;
};

我正在尝试解决相反的问题。即

给定一个嵌套的整数列表,返回其中所有整数的总和 按深度加权的列表。重量从根到增加 叶,现在权重是自下而上定义的。即叶级 整数的权重为 1,根级整数的权重最大 重量。

示例: [[1,1],2,[1,1]] ===> 解是 8。

我怎样才能使用相同的方法来解决这个问题?

(https://leetcode.com/problems/nested-list-weight-sum-ii/description/)

【问题讨论】:

  • 我会遍历以找到最大深度,然后在第二次遍历中应用您之前的算法。该链接仅供高级会员使用。
  • 感谢 ggorlen 的输入,您能告诉我它是如何工作的吗?我应该喜欢阵列上的 DFS 并首先找到最大深度吗?
  • 它不是真正的 DFS 或 BFS,因为您必须搜索整个结构,所以任何完全遍历都可以。我会发布一些代码,但我无法在您的链接上验证它。
  • ggorlen 是对的。它需要两次遍历——一次找到最大深度,然后一次计算结果。基于队列的 BFS 对两者都适用。
  • 如果您保留每个级别的总数列表,然后在遍历后将它们乘以它们的深度,则不需要两次遍历。

标签: javascript arrays algorithm array-algorithms


【解决方案1】:

这个应该完成这项工作,但我希望我有一个高级 leetcode 帐户来验证这一点。这个想法是进行搜索以找到结构中的最大深度,然后使用您以前的算法,但深度计算是相反的。此外,在没有递归的情况下执行它意味着更少的超时机会并且没有机会破坏堆栈。我添加了一些基本的测试用例,但同样不能保证。

const search = a => {
  let sum = 0;
  let depth = 0;
  const stack = [[a, 0]];

  while (stack.length) {
    const curr = stack.pop();

    if (curr[1] > depth) {
      depth = curr[1];
    }

    for (const e of curr[0]) {
      if (Array.isArray(e)) {
        stack.push([e, curr[1] + 1]);
      }
    }
  }

  stack.push([a, ++depth]);

  while (stack.length) {
    const curr = stack.pop();

    for (const e of curr[0]) {
      if (Array.isArray(e)) {
        stack.push([e, curr[1] - 1]);
      }
      else {
        sum += e * curr[1];
      }
    }
  }

  return sum;
};

console.log(search([[1,1],2,[1,1]]));
console.log(search([]));
console.log(search([6]));
console.log(search([[[[3]]]]));
console.log(search([[2],1]));

【讨论】:

  • 感谢分享这篇精彩的作品。谢谢!
【解决方案2】:

像您原来的depthSum 这样的基本递归解决方案可能无法满足第二个要求,因为您需要先计算出总深度,然后才能知道数组顶层项目的乘数。一种选择是首先计算出最深数组的深度,然后使用类似于您原来的 depthSum 的东西。

您可以使用reduce(这是将对象转换为单个值的适当方法)和条件(三元)运算符,以使您的代码简洁且重复性更少:

const depthCheck = (item) => (
  Array.isArray(item)
  ? 1 + Math.max(...item.map(depthCheck))
  : 0
);

// verification:
console.log(depthCheck([[1,1],2,[1,1]])); // total depth 2
console.log(depthCheck([[1,1],2,[1,1,[2,2]]])) // total depth 3
console.log(depthCheck([[1,1,[2,[3,3]]],2,[1,1,[2,2]]])) // total depth 4
console.log('-----')

const depthSum = (nestedList, weight=depthCheck(nestedList)) => (
  nestedList.reduce((a, val) => a + (
    Array.isArray(val)
    ? depthSum(val, weight - 1)
    : val * weight
  ), 0)
);

console.log(depthSum([[1,1],2,[1,1]])) // (2)*2 + (1+1+1+1)*1
console.log(depthSum([[1,1],2,[1,1,[2,2]]])) // (2)*3 + (1+1+1+1)*2 + (2+2)*1
console.log(depthSum([[1,1,[2,[3,3]]],2,[1,1,[2,2]]])) // (2)*4 + (1+1+1+1)*3 + (2)*2 + (3+3)*1

【讨论】:

  • 多么了不起的解决方案。太感谢了。会深入探讨!
【解决方案3】:

如果在遍历期间将每个深度的元素总和存储在数组中,则无需两次遍历嵌套数组即可执行此操作。之后,您知道该数组的长度是最大深度,您可以将总和乘以它们的正确权重。

可以使用递归或堆栈来完成遍历,如其他答案中所述。下面是一个使用递归的例子:

function weightedSum(array) {
    var sums = [], total = 0;
    traverse(array, 0);
    for (var i in sums)
        total += sums[i] * (sums.length - i);
    return total;

    function traverse(array, depth) {
        if (sums[depth] === undefined)
            sums[depth] = 0;
        for (var i in array) {
            if (typeof array[i] === "number")
                sums[depth] += array[i];
            else traverse(array[i], depth + 1);
        }
    }
}

console.log(weightedSum([[],[]]));
console.log(weightedSum([[1,1],2,[1,1]]));
console.log(weightedSum([1,[[],2,2],1,[[3,3,[[5]]],[3]],[]]));

【讨论】:

    【解决方案4】:

    也许你可以用一个简单的递归reducer来做如下。

    var weightOfNested = (a,d=1) => a.reduce((w,e) => Array.isArray(e) ? w + weightOfNested(e,d+1)
                                                                       : w + d*e, 0);
    console.log(weightOfNested([[1,1,[3]],2,[1,1]]));

    所以好的,正如评论中提到的,上面的代码更多地权衡了更深层次的元素。为了更多地权衡浅层,我们需要提前知道数组的深度。我相信这样或那样你最终会遍历数组两次......一次用于深​​度,一次用于计算加权和。

    var weightOfNested = (a, d = getDepth(a)) => a.reduce((w,e) => Array.isArray(e) ? w + weightOfNested(e,d-1)
                                                                                    : w + d*e, 0),
        getDepth       = (a, d = 1, t = 1) => a.reduce((r,e) => Array.isArray(e) ? r === t ? getDepth(e,++r,t+1)
                                                                                           : getDepth(e,r,t+1)
                                                                                 : r, d);
    console.log(weightOfNested([[1,1,[3]],2,[1,1]])); // depth is 3

    【讨论】:

    • 我认为这解决了基本版本,而不是反向重量版本。
    • @m69 是的。。谢谢你的提醒。我已经添加了一个正确的方法。不过,您的解决方案也是我认为的相同次数的遍历。
    • 好吧,输入数组总是比 sums 数组更长和/或更高维,所以我认为它在实践中会更快,即使所有方法的理论时间复杂度都是 O( N)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-22
    • 1970-01-01
    • 2022-11-06
    相关资源
    最近更新 更多