题意
给定一个 N x N 的二维数组,期望能找到一条波折路径,
路径起点是能从任何一个位置开始,终点也可以是任何一个位置。每个位置只能访问一次
波折路径是指相邻元素严格交替增减,每一个值相比前值要么是大于,要么是小于,而且是交替的,
上一个值比前一个值小,那么当前选择的值就应该比上一个值大。
eg:
input:
[1 0 1 0]
[1 0 1 1]
[1 0 1 0]
[1 0 1 1]
output:7
最长波折路径为 1 0 1 0 1 0 1
解法一:二维dp
- 状态定义:利用2个二维数组记录每个位置的最长波折路径长度
up[i][j]:以位置(i,j)结尾且最后一步是上升(当前元素比前一个大)的最长路径长度
down[i][j]:以位置(i,j)结尾且最后一步是下降(当前元素比前一个小)的最长路径长度
- 状态转移:对于每个位置
(i,j),检查其四个方向的相邻位置:
- 如果相邻位置的值比当前值小,则可以从该相邻位置的up状态转移到当前位置的down状态
- 如果相邻位置的值比当前值大,则可以从该相邻位置的down状态转移到当前位置的up状态
func main() {
matrix := [][]int{
{1, 0, 1, 0},
{1, 0, 1, 1},
{1, 0, 1, 0},
{1, 0, 1, 1},
}
fmt.Println(longestWavyPath(matrix))
}
func longestWavyPath(matrix [][]int) int {
if len(matrix) == 0 || len(matrix[0]) == 0 {
return 0
}
rows := len(matrix)
cols := len(matrix[0])
up := make([][]int, rows)
for i := range up {
up[i] = make([]int, cols)
}
down := make([][]int, rows)
for i := range down {
down[i] = make([]int, cols)
}
var res int
for i := 0; i < rows; i++ {
for j := 0; j < cols; j++ {
dfs(matrix, i, j, up, down, &res)
}
}
return res
}
func dfs(matrix [][]int, i int, j int, up [][]int, down [][]int, maxLen *int) {
if up[i][j] > 0 || down[i][j] > 0 {
return
}
up[i][j] = 1
down[i][j] = 1
dirs := [][]int{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}
for _, dir := range dirs {
x := i + dir[0]
y := j + dir[1]
if x < 0 || x >= len(matrix) || y < 0 || y >= len(matrix[0]) {
continue
}
dfs(matrix, x, y, up, down, maxLen)
if matrix[x][y] < matrix[i][j] {
up[i][j] = max(up[i][j], down[x][y]+1)
} else if matrix[x][y] > matrix[i][j] {
down[i][j] = max(down[i][j], up[x][y]+1)
}
currentMax := max(up[i][j], down[i][j])
if currentMax > *maxLen {
*maxLen = currentMax
}
}
}
func max(a, b int) int {
if a > b {
return a
}
return b
}