LeetCode——576. 出界的路径数(Out of Boundary Paths)[中等]——分析及代码(Java)

LeetCode——576. 出界的路径数[Out of Boundary Paths][中等]——分析及代码[Java]

一、题目

给你一个大小为 m x n 的网格和一个球。球的起始坐标为 [startRow, startColumn] 。你可以将球移到在四个方向上相邻的单元格内(可以穿过网格边界到达网格之外)。你 最多 可以移动 maxMove 次球。

给你五个整数 m、n、maxMove、startRow 以及 startColumn ,找出并返回可以将球移出边界的路径数量。因为答案可能非常大,返回对 10^9 + 7 取余 后的结果。

示例 1:

输入:m = 2, n = 2, maxMove = 2, startRow = 0, startColumn = 0
输出:6

示例 2:

输入:m = 1, n = 3, maxMove = 3, startRow = 0, startColumn = 1
输出:12

提示:

  • 1 <= m, n <= 50
  • 0 <= maxMove <= 50
  • 0 <= startRow < m
  • 0 <= startColumn < n

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/out-of-boundary-paths
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、分析及代码

1. 动态规划

(1)思路

根据题目特点,球每次只能向上、下、左、右 4 个固定的方向移动 1 格,可结合动态规划方法求解。

设计一个二维数组 dp,其中 dp[i][j] 表示当前以坐标 (i, j) 为终点的路径数量。在每个移动步中,统计可将球移出边界的路径数量,并根据本步移动情况更新 dp,直至用完所有移动次数。

(2)代码

class Solution {
    int m, n;
    int mod = (int)1e9 + 7;
    int[][] move = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};//移动方向

    public int findPaths(int m, int n, int maxMove, int startRow, int startColumn) {
        //初始化
        this.m = m;
        this.n = n;
        long ans = 0;
        long[][] dp = new long[m][n];//dp[i][j]表示当前以坐标(i, j)为终点的路径数量
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                dp[i][j] = 0;
        dp[startRow][startColumn] = 1;//初始化起点

        //动态规划
        for (int step = 0; step < maxMove; step++) {
            //统计当前移动步中,可以将球移出边界的路径数量
            for (int i = 0; i < m; i++)//上一移动步结束后,位于左右边界的路径,可在当前移动步中出界
                ans = (ans + dp[i][0] + dp[i][n - 1]) % mod;
            for (int j = 0; j < n; j++)//上一移动步结束后,位于上下边界的路径,可在当前移动步中出界
                ans = (ans + dp[0][j] + dp[m - 1][j]) % mod;
            
            //统计完成当前移动步后,以网格中各位置为终点的路径数量
            long[][] nextDp = new long[m][n];//nextDp[i][j]表示当前移动步结束后,以坐标(i, j)为终点的路径数量
            for (int i = 0; i < m; i++) {//遍历纵坐标
                for (int j = 0; j < n; j++) {//遍历横坐标
                    for (int k = 0; k < 4; k++) {//遍历4个移动方向
                        int x = i + move[k][0], y = j + move[k][1];//上一步可能的所处位置
                        if (inGrid(x, y))//判断该位置有效性
                            nextDp[i][j] = (nextDp[i][j] + dp[x][y]) % mod;//添加从(x,y)移动到当前位置(i,j)的路径数量
                    }
                }
            }
            for (int i = 0; i < m; i++)//复制nextDp到dp
                for (int j = 0; j < n; j++)
                    dp[i][j] = nextDp[i][j];
        }
        return (int)ans;
    }

    //判断当前位置是否在网格内
    public boolean inGrid(int x, int y) {
        return x >= 0 && x < m && y >= 0 && y < n;
    }
}

(3)结果

执行用时 :12 ms,在所有 Java 提交中击败了 56.09% 的用户;
内存消耗 :37.5 MB,在所有 Java 提交中击败了 73.19% 的用户。

三、其他

暂无。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值