列表

详情


2684. 矩阵中移动的最大次数

给你一个下标从 0 开始、大小为 m x n 的矩阵 grid ,矩阵由若干 整数组成。

你可以从矩阵第一列中的 任一 单元格出发,按以下方式遍历 grid

返回你在矩阵中能够 移动最大 次数。

 

示例 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
解释:从第一列的任一单元格开始都无法移动。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int maxMoves(vector<vector<int>>& grid) { } };

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

上一题