代码1,记忆化搜索:
- 在原切片 nums 前后各加一个位置,且值为 1 ,从而方便处理临界情况,处理过后的切片为val
- rec 二维切片进行记录值,从而达到记忆化递归的目的
- 递归参数,左下标,右下标,处理过的气球切片val,以及存储递归值的rec二维切片
- 递归结束条件,left不在right左边,因为递归进行了记忆化处理,所以在rec有值的情况下自然也可以直接返回
- for循环将所有情况计算,并且取最大值
- 最后返回最终的值
rec[left][right]
func maxCoins(nums []int) int {
n := len(nums)
val := make([]int, n + 2)
for i := 1; i <= n; i++ {
val[i] = nums[i - 1]
}
val[0], val[n+1] = 1, 1
rec := make([][]int, n + 2)
for i := 0; i < len(rec); i++ {
rec[i] = make([]int, n + 2)
for j := 0; j < len(rec[i]); j++ {
rec[i][j] = -1
}
}
return solve(0, n + 1, val, rec)
}
func solve(left, right int, val []int, rec [][]int) int {
if left >= right - 1 {
return 0
}
if rec[left][right] != -1 {
return rec[left][right]
}
for i := left + 1; i < right; i++ {
sum := val[left] * val[i] * val[right]
sum += solve(left, i, val, rec) + solve(i, right, val, rec)
rec[left][right] = max(rec[left][right], sum)
}
return rec[left][right]
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
代码2,动态规划:
代码 1 自顶向下递归求值,自然也可以,自底向上动态规划求值,从构造小问题,一步一步还原出大问题
func maxCoins(nums []int) int {
n := len(nums)
rec := make([][]int, n + 2)
for i := 0; i < n + 2; i++ {
rec[i] = make([]int, n + 2)
}
val := make([]int, n + 2)
val[0], val[n+1] = 1, 1
for i := 1; i <= n; i++ {
val[i] = nums[i-1]
}
for i := n - 1; i >= 0; i-- {
for j := i + 2; j <= n + 1; j++ {
for k := i + 1; k < j; k++ {
sum := val[i] * val[k] * val[j]
sum += rec[i][k] + rec[k][j]
rec[i][j] = max(rec[i][j], sum)
}
}
}
return rec[0][n+1]
}
func max(x, y int) int {
if x > y {
return x
}
return y
}