2684. 矩阵中移动的最大次数
给你一个下标从 0 开始、大小为 m x n
的矩阵 grid
,矩阵由若干 正 整数组成。
你可以从矩阵第一列中的 任一 单元格出发,按以下方式遍历 grid
:
(row, col)
可以移动到 (row - 1, col + 1)
、(row, col + 1)
和 (row + 1, col + 1)
三个单元格中任一满足值 严格 大于当前单元格的单元格。返回你在矩阵中能够 移动 的 最大 次数。
示例 1:
输入:grid = [[2,4,3,5],[5,4,9,3],[3,4,2,11],[10,9,13,15]] 输出:3 解释:可以从单元格 (0, 0) 开始并且按下面的路径移动: - (0, 0) -> (0, 1). - (0, 1) -> (1, 2). - (1, 2) -> (2, 3). 可以证明这是能够移动的最大次数。
示例 2:
输入:grid = [[3,2,4],[2,1,9],[1,1,7]] 输出:0 解释:从第一列的任一单元格开始都无法移动。
提示:
m == grid.length
n == grid[i].length
2 <= m, n <= 1000
4 <= m * n <= 105
1 <= grid[i][j] <= 106
原站题解
rust 解法, 执行用时: 20 ms, 内存消耗: 3.5 MB, 提交时间: 2024-03-16 11:48:45
impl Solution { pub fn max_moves(mut grid: Vec<Vec<i32>>) -> i32 { fn dfs(i: usize, j: usize, ans: &mut usize, grid: &mut Vec<Vec<i32>>) { if j > *ans { *ans = j } if *ans == grid[0].len() - 1 { // ans 已达到最大值 return; } // 向右上/右/右下走一步 for k in i.saturating_sub(1)..grid.len().min(i + 2) { if grid[k][j + 1] > grid[i][j] { dfs(k, j + 1, ans, grid); } } grid[i][j] = 0; } let mut ans = 0; for i in 0..grid.len() { dfs(i, 0, &mut ans, &mut grid); // 从第一列的任一单元格出发 } ans as i32 } pub fn max_moves2(grid: Vec<Vec<i32>>) -> i32 { let m = grid.len(); let n = grid[0].len(); let mut vis = vec![n; m]; let mut q = (0..m).collect::<Vec<_>>(); for j in 0..n - 1 { let mut nxt = Vec::new(); for &i in &q { for k in i.saturating_sub(1)..m.min(i + 2) { if vis[k] != j && grid[k][j + 1] > grid[i][j] { vis[k] = j; // 第 k 行目前最右访问到了 j nxt.push(k); } } } if nxt.is_empty() { // 无法再往右走了 return j as i32; } q = nxt; } (n - 1) as i32 } }
javascript 解法, 执行用时: 88 ms, 内存消耗: 60.3 MB, 提交时间: 2024-03-16 11:48:14
/** * @param {number[][]} grid * @return {number} */ var maxMoves = function(grid) { const m = grid.length, n = grid[0].length; const vis = Array(m).fill(-1); let q = [...Array(m).keys()]; for (let j = 0; j < n - 1; j++) { let nxt = []; for (const i of q) { for (let k = Math.max(i - 1, 0); k < Math.min(i + 2, m); k++) { if (vis[k] !== j && grid[k][j + 1] > grid[i][j]) { vis[k] = j; // 第 k 行目前最右访问到了 j nxt.push(k); } } } if (nxt.length === 0) { // 无法再往右走了 return j; } q = nxt; } return n - 1; }; // dfs var maxMoves2 = function(grid) { const m = grid.length, n = grid[0].length; let ans = 0; function dfs(i, j) { ans = Math.max(ans, j); if (ans === n - 1) { // ans 已达到最大值 return; } // 向右上/右/右下走一步 for (let k = Math.max(i - 1, 0); k < Math.min(i + 2, m); k++) { if (grid[k][j + 1] > grid[i][j]) { dfs(k, j + 1); } } grid[i][j] = 0; } for (let i = 0; i < m; i++) { dfs(i, 0); // 从第一列的任一单元格出发 } return ans; };
cpp 解法, 执行用时: 149 ms, 内存消耗: 65.3 MB, 提交时间: 2024-03-16 11:47:42
class Solution { public: int maxMoves(vector<vector<int>> &grid) { int m = grid.size(), n = grid[0].size(); int ans = 0; function<void(int, int)> dfs = [&](int i, int j) { ans = max(ans, j); if (ans == n - 1) { // ans 已达到最大值 return; } // 向右上/右/右下走一步 for (int k = max(i - 1, 0); k < min(i + 2, m); k++) { if (grid[k][j + 1] > grid[i][j]) { dfs(k, j + 1); } } grid[i][j] = 0; }; for (int i = 0; i < m; i++) { dfs(i, 0); // 从第一列的任一单元格出发 } return ans; } // bfs int maxMoves2(vector<vector<int>> &grid) { int m = grid.size(), n = grid[0].size(); vector<int> vis(m, -1), q(m); iota(q.begin(), q.end(), 0); for (int j = 0; j < n - 1; j++) { vector<int> nxt; for (int i : q) { for (int k = max(i - 1, 0); k < min(i + 2, m); k++) { if (vis[k] != j && grid[k][j + 1] > grid[i][j]) { vis[k] = j; // 第 k 行目前最右访问到了 j nxt.push_back(k); } } } if (nxt.empty()) { // 无法再往右走了 return j; } q = move(nxt); } return n - 1; } };
golang 解法, 执行用时: 176 ms, 内存消耗: 8.2 MB, 提交时间: 2023-05-23 10:04:48
func maxMoves(grid [][]int) (ans int) { m, n := len(grid), len(grid[0]) f := make([][]int, m) for i := range f { f[i] = make([]int, n) } for j := n - 2; j >= 0; j-- { for i, row := range grid { for k := max(i-1, 0); k < min(i+2, m); k++ { if grid[k][j+1] > row[j] { f[i][j] = max(f[i][j], f[k][j+1]+1) } } } } for _, r := range f { ans = max(ans, r[0]) } return } func min(a, b int) int { if b < a { return b }; return a } func max(a, b int) int { if b > a { return b }; return a }
java 解法, 执行用时: 17 ms, 内存消耗: 53.4 MB, 提交时间: 2023-05-23 10:04:36
class Solution { public int maxMoves(int[][] grid) { int m = grid.length, n = grid[0].length; var f = new int[m][n]; for (int j = n - 2; j >= 0; j--) for (int i = 0; i < m; i++) for (int k = Math.max(i - 1, 0); k < Math.min(i + 2, m); k++) if (grid[k][j + 1] > grid[i][j]) f[i][j] = Math.max(f[i][j], f[k][j + 1] + 1); int ans = 0; for (int i = 0; i < m; i++) ans = Math.max(ans, f[i][0]); return ans; } }
python3 解法, 执行用时: 716 ms, 内存消耗: 26.4 MB, 提交时间: 2023-05-23 10:04:16
# dp改成递推, class Solution: def maxMoves(self, grid: List[List[int]]) -> int: m, n = len(grid), len(grid[0]) f = [[0] * n for _ in range(m)] for j in range(n - 2, -1, -1): for i, row in enumerate(grid): for k in i - 1, i, i + 1: if 0 <= k < m and grid[k][j + 1] > row[j]: f[i][j] = max(f[i][j], f[k][j + 1] + 1) return max(row[0] for row in f)
golang 解法, 执行用时: 148 ms, 内存消耗: 8.6 MB, 提交时间: 2023-05-23 10:03:22
func maxMoves(grid [][]int) (ans int) { m, n := len(grid), len(grid[0]) memo := make([][]int, m) for i := range memo { memo[i] = make([]int, n) for j := range memo[i] { memo[i][j] = -1 // -1 表示没被计算过 } } var dfs func(int, int) int dfs = func(i, j int) (res int) { if j == n-1 { return } p := &memo[i][j] if *p != -1 { return *p } for k := max(i-1, 0); k < min(i+2, m); k++ { if grid[k][j+1] > grid[i][j] { res = max(res, dfs(k, j+1)+1) } } *p = res // 记忆化 return } for i := 0; i < m; i++ { ans = max(ans, dfs(i, 0)) } return } func min(a, b int) int { if b < a { return b }; return a } func max(a, b int) int { if b > a { return b }; return a }
python3 解法, 执行用时: 240 ms, 内存消耗: 42.2 MB, 提交时间: 2023-05-23 10:03:02
''' 写一个递归函数dfs(i,j),返回并记录从(i,j)出发时的答案。 枚举向右边的三个方向走,如果对应的格子没有出界,且格子值大于 grid[i][j], 则有 dfs(i,j) = max(dfs(i-1,j+1)+1,dfs(i,j+1)+1,dfs(i+1,j+1)+1) 递归边界:dfs(i,n-1)=0. 递归入口:dfs(i,0).取最大值即为答案。 ''' class Solution: def maxMoves(self, grid: List[List[int]]) -> int: m, n = len(grid), len(grid[0]) @cache def dfs(i: int, j: int) -> int: if j == n - 1: return 0 res = 0 for k in i - 1, i, i + 1: if 0 <= k < m and grid[k][j + 1] > grid[i][j]: res = max(res, dfs(k, j + 1) + 1) return res return max(dfs(i, 0) for i in range(m))
golang 解法, 执行用时: 152 ms, 内存消耗: 8.3 MB, 提交时间: 2023-05-23 10:00:27
func maxMoves(grid [][]int) int { m, n := len(grid), len(grid[0]) vis := make([]int, m) q := make([]int, m) for i := range q { q[i] = i } for j := 0; j < n-1; j++ { tmp := q q = nil for _, i := range tmp { for k := max(i-1, 0); k < min(i+2, m); k++ { if vis[k] != j+1 && grid[k][j+1] > grid[i][j] { vis[k] = j + 1 // 时间戳标记,避免重复创建 vis 数组 q = append(q, k) } } } if q == nil { return j } } return n - 1 } func min(a, b int) int { if b < a { return b }; return a } func max(a, b int) int { if b > a { return b }; return a }
python3 解法, 执行用时: 132 ms, 内存消耗: 24.6 MB, 提交时间: 2023-05-23 10:00:10
# bfs,每一轮向右搜索一列 class Solution: def maxMoves(self, grid: List[List[int]]) -> int: m, n = len(grid), len(grid[0]) q = range(m) vis = [-1] * m for j in range(n - 1): tmp = q q = [] for i in tmp: for k in i - 1, i, i + 1: if 0 <= k < m and vis[k] != j and grid[k][j + 1] > grid[i][j]: vis[k] = j # 时间戳标记,避免重复创建 vis 数组 q.append(k) if len(q) == 0: return j return n - 1