>[danger]小红拿到长度为n的数组,陡峭值是相邻两数差的绝对值之和,求只修改第i个元素,让f(i)最小的各个陡峭值 这个问题可以使用动态规划来解决。我们可以先计算出原数组的陡峭值,然后枚举每个元素,对于每个元素,假设我们将其修改为 x,那么它对答案的贡献就是:原本在 i-1 和 i 之间的两个数变成了 i-1 和 x 之间的数,以及 i 和 i+1 之间的两个数变成了 x 和 i+1 之间的数,所以它对答案的贡献就是: ``` abs(x - a[i-1]) + abs(x - a[i+1]) - abs(a[i] - a[i-1]) - abs(a[i] - a[i+1]) ``` 其中 a 是原数组,|x-y| 表示 x 和 y 之间的绝对距离。我们需要找到一个 x,使得上述表达式最小。 为了方便计算,我们可以先把原数组中相邻两个数之间的差的绝对值都计算出来,存入一个数组 b 中。也就是说,b[i] = |a[i]-a[i+1]|。 然后我们可以用一个数组 dp 来记录每个位置 i 修改后能够获得的最小的陡峭值。显然 dp[1] 一定是 0,因为第一个数无论如何都不会影响第一个陡峭值。接下来,我们从 2 开始枚举每个位置 i,对于每个位置 i,我们尝试将它修改为 0 到 n-1 中的每个数,计算上面的表达式,取最小值作为 dp[i] 的值。 转移方程如下: ``` dp[i] = min(dp[j] + abs(a[i]-a[j]) - b[j] + b[i-1] - abs(a[i-1]-a[j])) (j从1到n-1) ``` 其中 dp[j] 表示修改第 j 个元素后得到的最小陡峭值,abs(a[i]-a[j]) 表示修改 a[i] 后第 i 个差的绝对值变成了 abs(a[i]-a[j]),-b[j] 表示将第 j 个差的绝对值从原来的 b[j] 改成了 abs(a[i]-a[j]),b[i-1] 表示将原来在 i-1 和 i 之间的差的绝对值 b[i-1] 从原来的答案中撤销,abs(a[i-1]-a[j]) 表示把它改为 abs(a[i-1]-a[j]),因为现在第 i 位已经变成了 a[j]。 最终答案即为 min(dp[1]...dp[n-1])。 代码如下: ```javascript function solve(a) { const n = a.length; const b = new Array(n - 1); // 存储相邻两数之差的绝对值 for (let i = 0; i < n - 1; i++) { b[i] = Math.abs(a[i] - a[i + 1]); } const dp = new Array(n).fill(Infinity); dp[1] = 0; for (let i = 2; i < n; i++) { for (let j = 1; j < n - 1; j++) { dp[i] = Math.min(dp[i], dp[j] + Math.abs(a[i] - a[j]) - b[j] + b[i - 1] - Math.abs(a[i - 1] - a[j])); } } return Math.min(...dp.slice(1)); } ```