我被赋予了以下算法任务:
您将在下面输入一个三角形,并且需要根据下面的给定规则找到最大的数字总和;
您将从顶部开始,然后向下移动到下面的相邻数字。
只允许您对角向下走。
您只能在非主要号码上浏览。
您必须尽可能地到达金字塔的尽头。
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。
有人可以帮我遍历代码,看看有什么问题。
答案 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 - 1
,i
,i + 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]包含此节点以后的最大和(即,不是三角形中的原始值,而是修改后的值)。