带有质数检查的三角形中的Javascript最大路径总和

时间:2018-10-06 19:41:22

标签: javascript arrays algorithm

我被赋予了以下算法任务:

您将在下面输入一个三角形,并且需要根据下面的给定规则找到最大的数字总和;

您将从顶部开始,然后向下移动到下面的相邻数字。

只允许您对角向下走。

您只能在非主要号码上浏览。

您必须尽可能地到达金字塔的尽头。

           1
          8 4
        2  6  9
      8  5  9  3

如您所见,它具有符合“非主要数字”规则的几种路径; 1> 8> 6> 9,1> 4> 6> 9,1> 4> 9> 9 1 + 8 + 6 + 9 =24。如您所见,1、8、6、9都不是主要数字,并且行走超过这些将产生最大的总和。

根据上述规则,以下输入的最大和是多少?这意味着请将此金字塔作为实现的输入(直接在代码内部作为文件或常量),并通过使用它来解决。

                              215
                           193 124
                         117 237 442
                       218 935 347 235
                     320 804 522 417 345
                   229 601 723 835 133 124
                 248 202 277 433 207 263 257
               359 464 504 528 516 716 871 182
             461 441 426 656 863 560 380 171 923
           381 348 573 533 447 632 387 176 975 449
         223 711 445 645 245 543 931 532 937 541 444
       330 131 333 928 377 733 017 778 839 168 197 197
    131 171 522 137 217 224 291 413 528 520 227 229 928
  223 626 034 683 839 053 627 310 713 999 629 817 410 121
924 622 911 233 325 139 721 218 253 223 107 233 230 124 233

请注意,每个节点在这里只有两个孩子(最底部的孩子除外)。例如,您可以从215走到124(因为193是素数),然后从124走到237或442。从124您不能走到117,因为它不是124的直接子代。

    const isNotPrime = (num) => {
      for (let i = 2; i <= Math.sqrt(num); i++) {
      if (num % i === 0) return true;
      }
      return false;
      }

    function maximumTrianglePathSum(triangle) {

        function distilLastLine() {
          let lastLine = triangle.pop(),
              aboveLine = triangle.pop()
          for (let i = 0; i < aboveLine.length; i++)
          if(isNotPrime(lastLine[i]) && isNotPrime(lastLine[i + 1])){
            aboveLine[i] = Math.max(
              aboveLine[i] + lastLine[i],
              aboveLine[i] + lastLine[i + 1]
            )
          }else if(isNotPrime(lastLine[i]) && !isNotPrime(lastLine[i + 1]) ) {
            aboveLine[i] = aboveLine[i] + lastLine[i]
          }else if(!isNotPrime(lastLine[i]) && isNotPrime(lastLine[i + 1]) ){
            aboveLine[i] = aboveLine[i] + lastLine[i + 1]
          }
          triangle.push(aboveLine)
        }

        do {
          distilLastLine()
        } while (triangle.length > 1)
        return triangle[0][0]
      }

      // testing
      const myArray = [[1],
      [8, 4],
      [2, 6, 9], 
      [8, 5, 9, 3]]
      let theTriangle = [[215],
      [193, 124],
      [117, 237, 442],
      [218, 935, 347, 235],
      [320, 804, 522, 417, 345],
      [229, 601, 723, 835, 133, 124],
      [248, 202, 277, 433, 207, 263, 257],
      [359, 464, 504, 528, 516, 716, 871, 182],
      [461, 441, 426, 656, 863, 560, 380, 171, 923],
      [381, 348, 573, 533, 447, 632, 387, 176, 975, 449],
      [223, 711, 445, 645, 245, 543, 931, 532, 937, 541, 444],
      [330, 131, 333, 928, 377, 733, 17, 778, 839, 168, 197, 197],
      [131, 171, 522, 137, 217, 224, 291, 413, 528, 520, 227, 229, 928],
      [223, 626, 34, 683, 839, 53, 627, 310, 713, 999, 629, 817, 410, 121],
      [924, 622, 911, 233, 325, 139, 721, 218, 253, 223, 107, 233, 230, 124, 233]]

      console.log(maximumTrianglePathSum(myArray))
      console.log(maximumTrianglePathSum(theTriangle))

因此,实际上在第一个示例中,它打印的是23,而不是24,最大路径是24。

有人可以帮我遍历代码,看看有什么问题。

2 个答案:

答案 0 :(得分:1)

const isPrime = (num) => {
    for (let i = 2; i*i <= num; i++) {
        if (num % i === 0) return false;
    }    
    return num !== 1;
}

function maximumTrianglePathSum(triangle){
    if(triangle === undefined || triangle.length === 0 || triangle[0].length === 0 || isPrime(triangle[0][0])){
        return 0;
    }
    let sum_values = createEmptyTriangleStructure(triangle);
    for(let k = triangle.length - 1;k >= 0;--k){
        let currentLine = triangle[k];
        for (let i = 0; i < currentLine.length; i++){
            let curr_value = currentLine[i];
            if(isPrime(curr_value)){
                sum_values[k][i] = 0;
            }else if(k === triangle.length - 1){
                sum_values[k][i] = currentLine[i];   
            }else{
                if(i !== 0){
                    sum_values[k][i] = Math.max(sum_values[k][i],curr_value + sum_values[k + 1][i-1]); // left down diagonal
                }                
                sum_values[k][i] = Math.max(sum_values[k][i],curr_value + Math.max(sum_values[k + 1][i],sum_values[k + 1][i + 1]));// check with down value as well as right down diagonal
            }
        }
    }

    return sum_values[0][0];
}

function createEmptyTriangleStructure(triangle){
    let sum = [];
    for(let i=0;i < triangle.length; ++ i){
        sum[i] = [];
        for(let j = 0;j < triangle[i].length; ++ j){
            sum[i][j] = 0;
        }
    }
    return sum;
}

const myArray = [
                    [1],
                    [8, 4],
                    [2, 6, 9], 
                    [8, 5, 9, 3]
                ];
let theTriangle = [
                        [215],
                        [193, 124],
                        [117, 237, 442],
                        [218, 935, 347, 235],
                        [320, 804, 522, 417, 345],
                        [229, 601, 723, 835, 133, 124],
                        [248, 202, 277, 433, 207, 263, 257],
                        [359, 464, 504, 528, 516, 716, 871, 182],
                        [461, 441, 426, 656, 863, 560, 380, 171, 923],
                        [381, 348, 573, 533, 447, 632, 387, 176, 975, 449],
                        [223, 711, 445, 645, 245, 543, 931, 532, 937, 541, 444],
                        [330, 131, 333, 928, 377, 733, 17, 778, 839, 168, 197, 197],
                        [131, 171, 522, 137, 217, 224, 291, 413, 528, 520, 227, 229, 928],
                        [223, 626, 34, 683, 839, 53, 627, 310, 713, 999, 629, 817, 410, 121],
                        [924, 622, 911, 233, 325, 139, 721, 218, 253, 223, 107, 233, 230, 124, 233]
                    ];

console.log(maximumTrianglePathSum(myArray));
console.log(maximumTrianglePathSum(theTriangle));

  • 您的代码有很多问题。所以我改变了很多事情,我将尝试解释我在这里所做的事情。
  • isPrime()检查数字是否为质数(也请注意1)。
  • 请参阅第一个if条件,该条件处理许多极端情况。这样,如果第一行的第一个数字不是素数,我们会返回0,因为您是从顶部开始的,并且希望使用非素数数字。
  • 现在,我们创建一个sum_values数组,该数组将存储每一行​​的总和。该数组的结构与triangle相同,在0的帮助下,所有位置都初始化为createEmptyTriangleStructure()
  • 现在,我们将您的三角形从底部循环到顶部(这是您的想法)。
  • 如果我们在三角形行中遇到素数,由于无法从此处移至下方,因此我们将该位置设置为0中的sum_values
  • 如果我们要遍历三角形的最后一行,即else if(k === triangle.length - 1),则应按原样设置它们,因为在此之下没有行。
  • 最后,您被允许进行三步=> 左下(对角线)右下(对角线) => i - 1ii + 1
  • 因此,[k + 1][i - 1]down left[k + 1][i]down[k + 1][i + 1]down right

  • 因此,最后,我们在所有这些值中取max的值并将其设置为当前位置[k][i]的值。

  • 最后,我们返回[0][0],这是最终值。这是一个经典的动态编程问题。

  • 这可以在空间方面进行进一步优化。当前的空间复杂度为 O(n ^ 2),但我们可以将其降低为 O(n),我将其留给您练习。

答案 1 :(得分:0)

似乎有两个问题。

首先,isNotPrime(1)== False,但是1不是质数。

第二,如果lastLine [i]是素数,则函数distilLastLine禁止遍历节点。但是,lastLine [i]包含此节点以后的最大和(即,不是三角形中的原始值,而是修改后的值)。