【递归算法】不同路径Ⅲ

文章摘要:

  • 题目要求在给定的二维网格中,从起点到终点的所有路径必须经过所有无障碍方格且不重复。采用深度优先搜索(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;
                }
            }
        }
    }
}

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

相关推荐
骄马之死3 小时前
SpringMVC + SpringBoot 核心知识点总结
java·spring boot·后端
Frostnova丶4 小时前
【算法笔记】数学知识
笔记·算法
吴可可1234 小时前
AutoCAD 2016与2014二次开发关键差异
算法
郑洁文5 小时前
基于Spring Boot的流浪动物救助网站
java·spring boot·后端·毕设·流浪动物救助
雨白5 小时前
哈希:以时间换空间的算法实战
算法
螺丝钉code6 小时前
JAVA项目 Claude code CLAUDE.md 到底应该怎么写
java·人工智能·claude code
摇滚侠7 小时前
Maven 入门+高深 单一架构案例 54-59
java·架构·maven·intellij-idea
VidDown7 小时前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman
San813_LDD7 小时前
[数据结构]LeetCode学习
数据结构·算法·图论