【递归算法】不同路径Ⅲ

文章摘要:

  • 题目要求在给定的二维网格中,从起点到终点的所有路径必须经过所有无障碍方格且不重复。采用深度优先搜索(DFS)算法,先统计无障碍方格总数,再从起点开始递归搜索四个方向。当到达终点时检查路径步数是否等于总步数,相等则计入有效路径。通过回溯和访问标记确保不重复访问。最终返回所有有效路径的数量。

文章目录

题目链接: 980. 不同路径Ⅲ

一、题目解析

题目给出了一个二维网格 grid ,每一个方格中的数字都有不同含义:

  • 1 表示起始方格,在一个二维网格中只有一个起始方格
  • 2 表示结束方格,在一个二维网格中只有一个起始方格
  • 0 表示可以走的方格
  • -1 表示有障碍的方格,无法走

在每一个方格上可以往上下左右四个方向 走下一步,我们需要返回从起始方格结束方格的所有路径。

但是,存在限制条件:每一个无障碍的方格都需要通过一次,且每一条路径中的一个方格只能走一次。

因此我们需要确保每一条路径都要有效(即通过每一个无障碍方格没有重复走方格)。

例如,题目给出的二维网格如下:

  • grid = [ [ 1, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 2 ] ]
1 0 0 0
0 0 0 0
0 0 0 2

则有效的路径如下:

  1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2),(2,3)
1➡️ 0➡️ 0➡️ 0⬇️
⬇️0 ⬅️0 ⬅️0 ⬅️0
0➡️ 0➡️ 0➡️ 2🛑
  1. (0,0),(0,1),(1,1),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,3),(1,3),(2,3)
1➡️ 0⬇️ 0➡️ 0⬇️
⬇️0 ⬅️0 0⬆️ 0⬇️
0➡️ 0➡️ 0⬆️ 2🛑
  1. (0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(1,1),(0,1),(0,2),(0,3),(1,3),(2,3)
1⬇️ 0➡️ 0➡️ 0⬇️
0⬇️ ⬆️0 ⬅️0 0⬇️
0➡️ 0➡️ 0⬆️ 2🛑
  1. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2),(2,3)
1⬇️ 0➡️ 0➡️ 0⬇️
0⬇️ 0⬆️ ⬇️0 ⬅️0
0➡️ 0⬆️ ➡️0 2🛑

二、算法原理 + 代码实现

我们采用暴搜的思路解决这道题目,但是需要先遍历网格一遍,目的是统计一下网格中无障碍的方格的个数 ,然后加上起始位置和结束位置,结果是得到从起始方格到结束方格需要走过的总步数,这样能够筛选出通过所有无障碍方格的有效路径。

然后我们找到起始位置(即数字为 1 的方格),从起始位置开始深度优先遍历进行暴搜,递归搜索的时候维护一个用于记录步数的整型变量,每递归一个方格就加一。

当搜索到结束方格(数字为 2 )时,先看看记录步数的变量的值是否与之前统计的总步数相等,若不相等表示不是有效路径,若相等则表示是有效路径,这时候更新结果。

全局变量

为了方便递归,将题目给出的 grid 改为全局变量;整型变量 mn 表示二维网格的 行数 和 列数;然后是记录从起始方格到结束方格的总步数 step 和 记录有效路径数 ret

为了在递归搜索一条路径时不会重复走方格,我们依然利用一个和 grid 大小相同的布尔数组 visit 来实现;同时,为了在某个位置往上下左右四个方向搜索,我们定义两个向量数组 dxdy,其具体原理在 【递归算法】单词搜索 一文中。

java 复制代码
int[][] grid;
int m, n, step, ret;
boolean[][] visit;
int[] dx = {0, 0, -1, 1};
int[] dy = {-1, 1, 0, 0};

dfs 函数

函数头

我们给 dfs 函数设置的任务是:往指定位置的上下左右四个方向搜索并记录下递归的总步数。

因此,函数的参数需要知道 指定位置的下标 [row, col],同时设置一个整型变量参数 path 用于统计路径的步数。

java 复制代码
dfs(int row, int col, int path);

函数体

进入 dfs 函数时,先判断一下当前方格是否为结束方格(数字为 2),如果是结束方格,说明一条路径已经结束,这时候判断该路径是否是有效路径(通过记录路径步数的函数参数 path 和全局总步数比较是否相等),若是有效的路径,就更新结果,否则直接返回上一层。

然后再循环四次分别搜索该位置的上下左右四个方向,当满足 下标合法 且 方格未被走过 且 方格数字不为 -1 时,才继续递归搜索。

细节问题

回溯

回溯操作就是将 visit 数组的值修改回 false 即可。

剪枝

本题采用暴搜的策略解决,因此不涉及到剪枝的操作。

递归出口

递归出口就是遇到结束方格时返回,在 dfs 函数体中实现。

代码实现

java 复制代码
class Solution {
    int[][] grid;
    int m, n, step, ret;
    boolean[][] visit;
    int[] dx = {0, 0, -1, 1};
    int[] dy = {-1, 1, 0, 0};

    public int uniquePathsIII(int[][] givenGrid) {
        grid = givenGrid; m = grid.length; n = grid[0].length;
        visit = new boolean[m][n];

        // 先遍历一遍二维网格,统计网格中无障碍的方格数并记录下起始位置的坐标
        int x = 0, y = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 0) {
                    // 无障碍方格
                    step++;
                }
                if (grid[i][j] == 1) {
                    // 找到起始位置,记录坐标
                    x = i; y = j;
                }
            }
        }
        // 加上起始位置和结束位置的步数,就是所有步数
        step += 2;

        // 从起始位置开始深搜
        visit[x][y] = true;
        dfs(x, y, 1);

        return ret;
    }

    private void dfs(int row, int col, int path) {
        if (grid[row][col] == 2) {
            // 遇到结束方格,判断该路径是否有效
            if (path == step) {
                // 是有效路径
                ret++;
            }
            return;
        }

        // 从[row,col]的上下左右四个方向继续深搜
        for (int k = 0; k < 4; k++) {
            int x = row + dx[k], y = col + dy[k];
            if (x >= 0 && x < m && y >= 0 && y < n) {
                if (!visit[x][y] && grid[x][y] != -1) {
                    visit[x][y] = true;
                    dfs(x, y, path + 1);
                    visit[x][y] = false;
                }
            }
        }
    }
}

文章到这里就告一段落啦,若有错误请尽管指出~

相关推荐
想带你从多云到转晴2 小时前
07、数据结构与算法---优先级队列(堆)与排序
java·数据结构·算法
用户298698530142 小时前
Java 实现两个 Word 文档的差异比对
java·后端
吃好睡好便好2 小时前
在Matlab中绘制非默认峰值图
开发语言·学习·算法·matlab
sheeta19982 小时前
LeetCode 每日一题笔记 日期:2026.05.18 题目:1345. 跳跃游戏 IV
笔记·leetcode·游戏
小瓦码J码2 小时前
轻量化线程池实战:忙时并发、闲时归零,搞定周期批量任务
java·后端
NagatoYukee2 小时前
Java 商品交易实验(第二版)
java·开发语言
百珏2 小时前
[灰度发布]:灰度流量如何匹配与识别:从特征补全到网关命中引擎
java·后端·架构
Misnearch2 小时前
1345. 跳跃游戏 IV
java·leetcode·bfs
Bechamz2 小时前
大数据开发学习Day34
java·大数据·学习