数字三角形问题
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
规则:
- 在上面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大
- 只能往坐下或者右下走,如,第二行的 3,只能往第三行的 8 和 第三行的 1 走,走第三行的0是不行的(我开始这个规则也理解错误)
- 用眼睛看上往下自己加是错误的,应该从下往上加 (我开始也理解错了)
解题方法
1 、递归解法 不必须要的重复计算,低效 O (2的n次方)
function maxSumUsingRecursive(arr, i, j) {
let rowIndex = arr.length;
if (i == rowIndex - 1) {
return arr[i][j];
} else {
// 顶点的值+max(左侧支路的最大值,右侧支路的最大值)
return triangle[i][j] + Math.max(maxSumUsingRecursive(arr, i + 1, j), maxSumUsingRecursive(arr, i + 1, j + 1));
}
}
2、递归解法 缓存sum
function MaxSumCache(i, j, arr) {
const n = arr.length - 1;
let cache;
// 初始化一个缓存
if (MaxSumCache.cache) {
cache = MaxSumCache.cache
} else {
let _cache = []
for (let i = 0; i <= n; i++) {
_cache.push([])
}
cache = _cache
MaxSumCache.cache = cache;
}
//这个数字的最大值已经被求出来了
if (cache[i][j] != undefined) {
return cache[i][j];
}
//如果i==n,那就说明它已经是最后一行的那个数字了, 那最大和就是那个数字它自己
if (i == n) {
cache[i][j] = arr[i][j];
} else {
//否则就要算一下 它正下方的那个数字走到底边得到的最大和是什么
cache[i][j] = Math.max(MaxSumCache(i + 1, j, arr), MaxSumCache(i + 1, j + 1, arr)) + arr[i][j];
}
return cache[i][j];
}
3 、 递推法 从最后一行,往上算, 避免了重复运算,O(n2)
function ditui(arr, i, j) {
let n = arr.length, dp = [];
let m = n - 1;
// 把结果全部放到dp数组,从数组最后一层递推上去
dp[m] = [...arr[m]];
for (let a = m - 1; a >= 0; a--) {
dp[a] = []
for (let b = 0; b <= a; b++) {
dp[a][b] = arr[a][b] + Math.max(dp[a+1][b], dp[a+1][b+1])
}
}
return dp[i][j]
}