重复子数组的最大长度(代码)

时间:2019-12-29 20:58:48

标签: javascript algorithm dynamic-programming

我正在查看此leetcode question,并且在完成幼稚方法时遇到了问题。我能够找到最佳解决方案here。但是我不确定天真的尝试有什么问题。

问题如下:

  

给出两个整数数组A和B,返回一​​个   出现在两个数组中的子数组。

     

示例:
  输入:A:[1,2,3,2,1] B:[3,2,1,4,7]

     

输出:3

     

说明:最大长度的重复子数组为[3,2,1]。

这是我当前的代码:

var findLength = function(a, b) {
    if (a.length === 0 || b.length === 0) {
        return 0;
    }

    let aWithoutFinalNumber = a.slice(0, a.length - 1);
    let bWithoutFinalNumber = b.slice(0, b.length - 1);

    let aFinalNumber = a[a.length - 1];
    let bFinalNumber = b[b.length - 1];

    // matching numbers
    if(aFinalNumber === bFinalNumber) {
        return 1 + findLength(aWithoutFinalNumber, bWithoutFinalNumber);
    } else { // mismatch. Compete to find the maximum length.
        return Math.max(findLength(a, bWithoutFinalNumber), findLength(aWithoutFinalNumber, b));
    }
};

我的解决方案通过了多个测试案例,但在诸如a: [0,1,1,1,1] b: [1,0,1,0,1]之类的案例中失败了。对我的错误有任何见解将不胜感激!

3 个答案:

答案 0 :(得分:1)

您可以使用嵌套循环,当两个数组中出现相同的元素时,您可以开始递增两个索引,直到两个数组中的元素相同为止。为您提供最大元素集的结果将是返回的结果。

function maxSub(a, b) {
  let result = null;

  function findAll(i, j) {
    const res = [];

    if (a[i] !== b[j] || a[i] == undefined || b[j] == undefined) {
      return res;
    }

    return res.concat(a[i], ...findAll(i + 1, j + 1))
  }

  a.forEach((e, i) => {
    b.forEach((c, j) => {
      if (e == c) {
        const sub = findAll(i, j);

        if (!result || sub.length > result.length) {
          result = sub
        }
      }
    })
  })

  return result;
}


console.log(maxSub([0, 1, 1, 1, 1], [1, 0, 1, 0, 1]))
console.log(maxSub([1, 2, 3, 2, 1], [3, 2, 1, 4, 7]))

答案 1 :(得分:1)

问题来自最后一个元素匹配时计算最大长度的方式。这是一个最小的示例:

var findLength = function(a, b) {
    if (a.length === 0 || b.length === 0) {
        return 0;
    }

    let aWithoutFinalNumber = a.slice(0, a.length - 1);
    let bWithoutFinalNumber = b.slice(0, b.length - 1);

    let aFinalNumber = a[a.length - 1];
    let bFinalNumber = b[b.length - 1];

    // matching numbers
    if(aFinalNumber === bFinalNumber) {
        return 1 + findLength(aWithoutFinalNumber, bWithoutFinalNumber); //< -- problem here
    } else { // mismatch. Compete to find the maximum length.
        return Math.max(findLength(a, bWithoutFinalNumber), findLength(aWithoutFinalNumber, b));
    }
};

console.log(findLength([1, 0, 2, 1], [1, 0, 3, 1]));

如果有任何匹配项,请在最大长度上添加1,但是如果以后有不匹配项,则不一定是正确的。为了简化理解,以下是插图的简化版本:

[1, 0, 2, 1]
          ^-------|
[1, 0, 3, 1]      | -- match, max length +1
          ^-------|
______

[1, 0, 2, 1]
       ^----------|
[1, 0, 3, 1]      | -- mismatch, max length +0
       ^----------|

______

[1, 0, 2, 1]
    ^-------------|
[1, 0, 3, 1]      | -- match, max length +1
    ^-------------|

______

[1, 0, 2, 1]
 ^----------------|
[1, 0, 3, 1]      | -- match, max length +1
 ^----------------|

所有匹配项总计时,您得到3,但是,如果不匹配,则应该重置该计数。

可以为避免该问题而对算法进行的一个简单更改是将当前计数作为参数传递给函数。这样,您可以控制何时需要重置计数:

var findLength = function(a, b, maxSoFar = 0) { //<-- default count of zero
    if (a.length === 0 || b.length === 0) {
        return maxSoFar; //<-- return the count
    }

    let aWithoutFinalNumber = a.slice(0, a.length - 1);
    let bWithoutFinalNumber = b.slice(0, b.length - 1);

    let aFinalNumber = a[a.length - 1];
    let bFinalNumber = b[b.length - 1];

    // matching numbers
    if(aFinalNumber === bFinalNumber) {
        const newMax = maxSoFar + 1; //<-- increment the count
        return Math.max(newMax, findLength(aWithoutFinalNumber, bWithoutFinalNumber, newMax)); //<-- return the newMax in case the next is a mismatch
    } else { // mismatch. Compete to find the maximum length.
        return Math.max(findLength(a, bWithoutFinalNumber), findLength(aWithoutFinalNumber, b)); //<-- reset the count
    }
};

console.log(findLength([1, 0, 2, 1], [1, 0, 3, 1]));
console.log(findLength([1, 2, 3, 2, 1], [3, 2, 1, 4, 7]));
console.log(findLength([0, 1, 1, 1, 1], [1, 0, 1, 0, 1]));

答案 2 :(得分:1)

您也可以将 dp 与表格一起使用。我尝试了其他代码,它在以下情况下出错:[0,0,0,0,1,0,0] 和 [0,0,0,0,0,1,0]。 这是相同的python代码。

def findLength(a, b):
    if len(a)==0 or len(b)==0:
        return 0
        
    n=len(a)
    m=len(b)

    dp=[[0 for _ in range(n+1)] for _ in range(m+1)]
    maxSoFar=0
       
    for i in range(1,m+1):
        for j in range(1,n+1):
            if a[j-1]==b[i-1]:
                dp[i][j]=dp[i-1][j-1]+1
                maxSoFar=max(maxSoFar,dp[i][j])
            else:
                dp[i][j]=0
                    
    return maxSoFar