【每日一题Day285】LC980不同路径 III | 回溯

简介: 【每日一题Day285】LC980不同路径 III | 回溯

不同路径 III【LC980】

在二维网格 grid 上,有 4 种类型的方格:

  • 1 表示起始方格。且只有一个起始方格。
  • 2 表示结束方格,且只有一个结束方格。
  • 0 表示我们可以走过的空方格。
  • -1 表示我们无法跨越的障碍。
  • 返回在四个方向(上、下、左、右)上行走时,从起始方格到结束方格的不同路径的数目**。**

每一个无障碍方格都要通过一次,但是一条路径中不能重复通过同一个方格

  • 思路从起点出发,寻找经过所有空格到达终点的路径个数
  • 首先遍历一遍矩阵,找到起点位置、终点位置以及空格数量
  • 然后通过dfs+回溯的方式,寻找有效路径,为了防止重复遍历,还需要使用visit数组记录每个结点的访问状态

实现

  • loc(当前位置)
  • left(当前剩余的空格数量)
  • 全局变量:gridvisit
  • 返回值 int:从当前位置当终点的路径个数
  • 回溯函数终止条件
  • 到达终点时返回,如果剩余空格个数为0,返回1;反之,返回0
  • 首先判断当前位置是否访问过【记忆化,优化不明显】
  • 然后判断是否到达终点
  • 再向四个方向进行移动,需要判断坐标是否合法、是否被访问过、是否是障碍物
class Solution {
    int m, n;
    boolean[][] visit;
    int[][] grid;
    int[] dir = {0, 1, 0, -1, 0};
    int[] end;
    int[][] dp;
    public int uniquePathsIII(int[][] grid) {
        this.m = grid.length;
        this.n = grid[0].length;
        this.visit = new boolean[m][n];
        this.grid = grid;
        int[] start = new int[2];
        this.end = new int[2];
        this.dp = new int[m][n];
        int total = 0;
        for (int i = 0; i < m; i++){
            Arrays.fill(dp[i], -1);
            for (int j = 0; j < n; j++){
                if (grid[i][j] == 1){
                    start[0] = i;
                    start[1] = j;
                }else if (grid[i][j] == 2){
                    end[0] = i;
                    end[1] = j;
                    total++;
                }else if (grid[i][j] == 0){
                    total++;
                }
            }
        }
        visit[start[0]][start[1]] = true;
        return dfs(start, total);
    }
    public int dfs(int[] loc, int left){
        if (dp[loc[0]][loc[1]] != -1) return dp[loc[0]][loc[1]];
        if (loc[0] == end[0] && loc[1] == end[1]){
            if (left == 0){
                return 1;
            }else{
                return 0;
            }
        }
        int res = 0;        
        for (int i = 0; i < 4; i++){
            int[] u = {loc[0] + dir[i], loc[1] + dir[i + 1]};
            if (u[0] >= 0 && u[0] < m && u[1] >= 0 && u[1] < n && !visit[u[0]][u[1]] && grid[u[0]][u[1]] != -1){
                visit[u[0]][u[1]] = true;
                res += dfs(u, left - 1);
                visit[u[0]][u[1]] = false;
            }
        }
        return res;
    }
}

image.png

目录
相关文章
|
小程序 搜索推荐 安全
【开题报告】基于uniapp的在线蛋糕商城小程序的设计与实现
【开题报告】基于uniapp的在线蛋糕商城小程序的设计与实现
611 0
|
Ubuntu Java
百度搜索:蓝易云【Ubuntu22系统安装OpenJDK详细教程。】
现在,你已经成功在Ubuntu 22系统上安装了OpenJDK。你可以使用Java命令执行Java程序,并进行Java开发。
282 0
【数据结构课设】家谱管理系统(内附源码)
家谱管理系统是数据结构课程的一个经典的课程设计,也算是一个比较庞大的程序了吧,写出来还是蛮不容易的!分享出来希望能对大家有帮助!
【数据结构课设】家谱管理系统(内附源码)
|
11月前
|
小程序 机器人 开发者
QQ 小程序已发布,但无法被搜索的解决方案
我的 QQ 小程序在 2024 年 8 月就已经审核通过,上架后却一直无法被搜索到。打开后,再在 QQ 上下拉查看 “最近使用”,发现他出现一下又马上消失。
189 2
|
11月前
|
存储 自然语言处理 数据可视化
3倍提升效率:医疗病理信息抽取与关系图谱展示系统解析
该项目旨在通过NLP技术将医疗病理报告中的非结构化文本转化为结构化数据,实现信息的高效抽取、存储及可视化展示。利用Python、JavaScript等技术栈,结合Echarts等工具,构建病理信息的关系图谱,支持多条件检索与图表互动,提高医生及研究人员的工作效率。预期成果包括数据结构化、关系图谱可视化、快速检索及数据统计分析等功能。项目预计2-4周完成。
207 0
|
存储 异构计算
贴片卡与插拔卡
在“贴片卡”和“插拔卡”的操作时,首先需要明确这两种操作通常与电子设备中的物理部件有关,尤其是在需要频繁更换或配置的设备中。不过,由于“贴片卡”和“插拔卡”并不是广泛认可的通用术语,我会基于通常的理解来解释这些操作在类似上下文中的应用。
|
设计模式 前端开发 数据库
理解mvc架构
mvc架构
167 4
|
JavaScript 前端开发 容器
< 每日小技巧: 基于Vue状态的过渡动画 - Transition 和 TransitionGroup>
Vue 的 `Transition` 和 `TransitionGroup` 是用于状态变化过渡和动画的组件。`Transition` 适用于单一元素或组件的进入和离开动画,而 `TransitionGroup` 用于 v-for 列表元素的增删改动画,支持 CSS 过渡和 JS 钩子。
375 1
< 每日小技巧: 基于Vue状态的过渡动画 - Transition 和 TransitionGroup>
|
安全 5G 数据安全/隐私保护
|
存储 SQL Oracle
细说MySQL锁机制:S锁、X锁、意向锁...
好久没有深入地写文章了,这次来发一篇,通过mysql事物 | Joseph's Blog (gitee.io)和其他一些博客有感进行一些补充,InnoDB详解在下期发布 加锁机制 乐观锁和悲观锁 之前在JVM中其实也讲到,JVM在对象初始化的过程中其实也是使用的乐观锁
881 0
细说MySQL锁机制:S锁、X锁、意向锁...