一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情。
题目
你有一个凸的 n 边形,其每个顶点都有一个整数值。给定一个整数数组 values ,其中 values[i] 是第 i 个顶点的值(即 顺时针顺序 )。
假设将多边形 剖分 为 n - 2 个三角形。对于每个三角形,该三角形的值是顶点标记的乘积,三角剖分的分数是进行三角剖分后所有 n - 2 个三角形的值之和。
返回 多边形进行三角剖分后可以得到的最低分 。
示例 1:
输入:values = [1,2,3]
输出:6
解释:多边形已经三角化,唯一三角形的分数为 6。
示例 2:
输入:values = [3,7,4,5]
输出:144
解释:有两种三角剖分,可能得分分别为:3*7*5 + 4*5*7 = 245,或 3*4*5 + 3*4*7 = 144。最低分数为 144。
示例 3:
输入:values = [1,3,1,4,1,5]
输出:13
解释:最低分数三角剖分的得分情况为 1*1*3 + 1*1*4 + 1*1*5 + 1*1*1 = 13。
提示:
n == values.length3 <= n <= 501 <= values[i] <= 100
思考
本题难度中等。不过,该题咋一看没什么思路,自我感觉还是很难的!
定义dp[i][j]为区间[i, j]的三角剖分最低得分, 因此题目所求即为dp[0][n - 1]。
显然,当我们只取出1个顶点(i == j)或只取出两个顶点(i + 1 == j)时,无法组成三角形,此时 dp[i][j] === 0。
递推过程是从左下到右上的,因此 i 取值 n - 3,j 取值 i + 2,而 m 在(i,j)范围内进行遍历。状态转移方程为:dp[i][j] = Math.min(dp[i][j], values[i] * values[j] * values[m] + dp[i][m] + dp[m][j])。
解答
方法一:动态规划
/**
* @param {number[]} values
* @return {number}
*/
var minScoreTriangulation = function(values) {
let n = values.length
const dp = new Array(n).fill(0).map(() => new Array(n).fill(0))
for (let i = n - 3; i >= 0; i--) {
for (let j = i + 2; j < n; j++) {
for (let m = i + 1; m < j; m++) {
if(dp[i][j] === 0) {
dp[i][j] = values[i] * values[j] * values[m] + dp[i][m] + dp[m][j]
} else {
dp[i][j] = Math.min(dp[i][j], values[i] * values[j] * values[m] + dp[i][m] + dp[m][j])
}
}
}
}
return dp[0][n - 1]
}
// console.log(minScoreTriangulation([1,2,3])) // 6
// console.log(minScoreTriangulation([3,7,4,5])) // 144
// 执行用时:72 ms, 在所有 JavaScript 提交中击败了25.00%的用户
// 内存消耗:42.2 MB, 在所有 JavaScript 提交中击败了50.00%的用户
// 通过测试用例:94 / 94
复杂度分析
- 时间复杂度:O(n^3),n为数组values的长度。
- 空间复杂度:O(n^2),需要构建二维数组dp。