Given a 2D integer matrix, find a snake sequence with maximum length. A snake sequence can move only right or down; a move from cell a to adjacent cell b is allowed only if abs(a - b) == 1 (difference of exactly 1).
Return one such maximum-length sequence of values (reading sequence in traversal order). If multiple sequences have the same maximum length, any one is acceptable. If the matrix is empty, return an empty sequence.
We use dynamic programming (bottom-up). For every cell (i,j) we compute dp[i][j] — the length of the longest snake sequence that ends at (i,j) when moves are restricted to coming from the top or left. While filling dp we track the cell with the global maximum length, then reconstruct the path by stepping to a neighbor with dp == current-1 whose value differs by one.
Method 1 — Dynamic Programming (Bottom-up) with path reconstruction#
If a valid snake sequence ends at cell (i,j), its previous cell must be either (i-1,j) (from above) or (i,j-1) (from left). So the best length ending at (i,j) is 1 + max(dp[i-1][j], dp[i][j-1]) for those neighbors where abs(mat[neighbor] - mat[i][j]) == 1. Fill dp row-major and track the maximum cell.
Let m = rows, n = cols. Create dp (m×n) filled with 1 (each cell by itself is length 1).
Iterate i from 0..m-1, j from 0..n-1:
If i > 0 and abs(mat[i][j] - mat[i-1][j]) == 1, set dp[i][j] = max(dp[i][j], dp[i-1][j] + 1).
If j > 0 and abs(mat[i][j] - mat[i][j-1]) == 1, set dp[i][j] = max(dp[i][j], dp[i][j-1] + 1).
Track maxLen and coordinates (r,c) of the cell with maximum dp.
Reconstruct path starting from (r,c): while dp[r][c] > 0, append mat[r][c] to path and move to a neighbor (r-1,c) or (r,c-1) with dp == dp[r][c] - 1 and abs(mat[neighbor] - mat[r][c]) == 1 (prefer up if both possible). Stop when no predecessor found or dp drops to 1. Reverse path and return it.
Edge cases covered: empty matrix, single row/column matrices, multiple paths with same length (we return any).
from typing import List
classSolution:
deflongestSnakeSequence(self, mat: List[List[int]]) -> List[int]:
ifnot mat: return []
m, n = len(mat), len(mat[0])
dp = [[1]*n for _ in range(m)]
max_len, r, c =1, 0, 0for i in range(m):
for j in range(n):
if i >0and abs(mat[i][j] - mat[i-1][j]) ==1:
dp[i][j] = max(dp[i][j], dp[i-1][j] +1)
if j >0and abs(mat[i][j] - mat[i][j-1]) ==1:
dp[i][j] = max(dp[i][j], dp[i][j-1] +1)
if dp[i][j] > max_len:
max_len, r, c = dp[i][j], i, j
path = []
while max_len >0:
path.append(mat[r][c])
if r >0and dp[r-1][c] == dp[r][c] -1and abs(mat[r][c] - mat[r-1][c]) ==1:
r -=1elif c >0and dp[r][c-1] == dp[r][c] -1and abs(mat[r][c] - mat[r][c-1]) ==1:
c -=1else:
break max_len -=1return path[::-1]