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

本文介绍了如何使用深度优先搜索(DFS)算法解决二维网格中的路径问题,计算从唯一起始方格到唯一结束方格,经过所有空格且不重复经过的路径数量。算法考虑了障碍物和空格的限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

不同路径 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;
        }
    }
    
    • 时间复杂度:O(3mn)O(3^{mn})O(3mn),除了起始位置可以向四个方向遍历,其余位置最多向3个方向遍历
    • 空间复杂度:O(mn)O(mn)O(mn)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值