剑指offer.13.机器人的运动范围之DFS、BFS搜索

2023-11-11

前言

对于矩阵搜索问题,就像图的搜索一样,熟练掌握DFS、BFS是关键。

一、DFS

1、思想

通过DFS去寻找满足条件的格子,而已经访问过的格子就要标记一下。当遇到递归出口时,返回一次就+1。从{0,0}开始行走,走的地方只能是下面和右面。

2、源码

	int[][] visited;
    int maxi, maxj, k;

    public int movingCount(int m, int n, int k) {
        //设置每个递归函数要使用的公共参数
        visited = new int[m][n];
        maxi = m;
        maxj = n;
        this.k = k;
        //调用递归求解
        return DFS(0, 0);

    }

    //DFS+剪枝
    public int DFS(int i, int j) {
        //递归出口
        if (i == maxi || j == maxj || visited[i][j] == 1 || sum(i) + sum(j) > k)
            return 0;
        visited[i][j] = 1;
        //从第一个节点出发,向右走和向下走就可以遍历完所有可达节点
        return DFS(i + 1, j) + DFS(i, j + 1) + 1;
    }

    //给定一个数字,在100之类,计算它所有位数之和
    public int sum(int data) {
        int sum = 0;
        while (data > 0) {
            sum += data % 10;
            data /= 10;
        }
        return sum;
    }

因为数据0<=data<=100,所以也可以写成(data % 10 + data / 10)

二、BFS

通过辅助队列完成所有格子的遍历,加入队列中的格子要标记为已访问过。

1、源码

//BFS寻找矩阵格子数
    public int movingCount(int m, int n, int k) {
        //用队列完成BFS
        int[][] visited = new int[m][n];
        int result = 1;
        List<Grid> queue = new LinkedList<>();
        int i = 0, j = 0;
        visited[i][j] = 1;
        queue.add(new Grid(i, j));
        Grid grid = null;
        while (queue.size() != 0) {
            grid = queue.remove(0);
            i = grid.getI();
            j = grid.getJ();
            if (i < m - 1 && visited[i + 1][j] == 0 && sum(i + 1) + sum(j) <= k) {
                queue.add(new Grid(i + 1, j));
                visited[i + 1][j] = 1;
                result++;
            }
            if (j < n - 1 && visited[i][j + 1] == 0 && sum(i) + sum(j + 1) <= k) {
                queue.add(new Grid(i, j + 1));
                visited[i][j + 1] = 1;
                result++;
            }
        }
        return result;
    }
    //给定一个数字,在100之类,计算它所有位数之和
    public int sum(int data) {
        int sum = 0;
        while (data > 0) {
            sum += data % 10;
            data /= 10;
        }
        return sum;
    }
    class Grid {
        int i;
        int j;

        public Grid(int i, int j) {
            this.i = i;
            this.j = j;
        }

        public int getI() {
            return i;
        }

        public int getJ() {
            return j;
        }
    }

注:上面写起来稍显复杂,第一,可以不用Grid这个类;第二,DFS种两个if显得太多,毕竟里面的操作是类似的。

2、改进源码BFS

//BFS寻找矩阵格子数
    public int movingCount(int m, int n, int k) {
        //用队列完成BFS
        int[][] visited = new int[m][n];
        Queue<int[]> queue = new LinkedList<>();
        int i = 0, j = 0;
        visited[i][j] = 1;
        queue.offer(new int[]{i,j});
        int result = 1;
        int[] grid;
        //设置辅助矩阵
        int[][] E = new int[][]{{1,0},{0,1}};
        while (!queue.isEmpty()) {
            grid = queue.poll();
            i = grid[0];
            j = grid[1];
            for(int count = 0;count < 2;count++){
                int newi = i + E[0][count];
                int newj = j + E[1][count];
                if (newi >= m || newj >= n || visited[newi][newj] == 1 || newi % 10 + newi / 10 + newj % 10 + newj / 10 > k)
                    continue;
                queue.offer(new int[]{newi, newj});
                visited[newi][newj] = 1;
                result++;
            }
        }
        return result;
    }

总结

1)时间复杂度,O(mn),mn为总格子数。
2)空间复杂度,O(mn),mn为visited矩阵的大小。递归栈的深度最大也为mn,当只有一列时。
注:掌握DFS、BFS是解决矩阵搜索、图搜索的关键基础。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

剑指offer.13.机器人的运动范围之DFS、BFS搜索 的相关文章

随机推荐

  • Jmeter做接口测试-面试题

    一 请说明你用Jmeter做接口测试的整体过程 用Jmeter做接口测试 至少要经过以下几步 1 根据开发提供的接口文档 编写接口测试用例 2 利用JMeter做接口测试 添加线程组和HTTP请求 在HTTP请求中 添加对应的ip地址 端口
  • http连接处理(下)(四)

    1 结合代码分析请求报文响应 下面我们将介绍服务器如何响应请求报文 并将该报文发送给浏览器端 首先介绍一些基础API 然后结合流程图和代码对服务器响应请求报文进行详解 基础API部分 介绍stat mmap iovec writev 流程图
  • CRC算法并行运算Verilog实现

    因为CRC循环冗余校验码的算法和硬件电路结构比较简单 所以CRC是一种在工程中常用的数据校验方法 尽管CRC简单 但在工程应用中还是有些问题会对工程师产生困惑 这篇文章将介绍一下CRC 希望对大家有所帮助 一 CRC算法介绍 CRC校验原理
  • Visual Studio安装时,不能更改共享组件、工具和SDK的位置

    之前安装的时候把安装路径改了 之后卸载不干净 注册表还留有缓存 不能更改位置 如下图 微软官方提供的卸载工具 TotalUninstaller 卸载不干净可以用这个工具 解决办法 更改注册表 HKEY LOCAL MACHINE SOFTW
  • KNN算法分类问题实现介绍和使用

    KNN算法详解 sklearn包介绍 一 sklearn包使用KNN算法 1 准备数据 X np array 5 1 3 5 1 4 0 2 4 9 3 1 4 0 2 4 7 3 2 1 3 0 2 4 6 3 1 1 5 0 2 5 3
  • uniapp的websocket的使用

    1 websocket的封装 uniapp获取websocket返回来的数据可以采用Vuex进行存储 class websocketUtil constructor url time url 是请求的后端的地址 time 是心跳包的时间 t
  • 【MAC终端UI自动化】获取当前最前端的应用程序

    目的 在操作当前应用后 弹出一个系统弹窗 想定位到这个弹窗 方法一 没搞定 期待大佬解答 想到atomac有个获取当前最前端的应用程序的方法getFrontmostApp a atomac getFrontmostApp print a 返
  • Proxy error: Could not proxy request... 问题解决

    背景 最近在项目中发现一个问题 每次npm run serve 时都是正常的 每次重新编译后就会有下面的提示 Proxy error Could not proxy request Manage repairDelivery settlem
  • cppkafka是什么 和librdkafka关系

    最近日志审计对接日志中心的开发 需要设计kafka相关的一些东西 因此了解了一些 在github 的 kafka官网上看到有 Language bindings 不太清楚其中的 cppkafka 是什么东西 能用来做什么 多方了解后才明白
  • C语言树莓派PICO,RP2040(树莓派Pico) PIO – 实例分析&编程

    这次拿来开刀的是WS2812 具体代码可见 gt https github com raspberrypi pico examples blob master pio ws2812 ws2812 pio program ws2812 sid
  • 什么是边缘计算网关?

    边缘计算网关 简称 边缘网关 将云端功能扩展到本地的边缘设备 使边缘设备能够快速自主地响应本地事件 提供低延时 低成本 隐私安全 本地自治的本地计算服务 同时所有服务都以 Docker 镜像方式安装 真正做到了跨平台 部署快捷 易管理 在链
  • MYSQL----union与limit

    union 1 union操作符用于合并两个或多个 SELECT 语句的结果集 2 union内部的 SELECT 语句必须拥有相同数量的列 列也必须拥有相似的数据类型 同时 每条 SELECT 语句中的列的顺序必须相同 limit 1 l
  • Jmeter使用篇(六) : Jmeter集合点

    配置Jmeter集合点的方法 1 需要设置集合点 进行并发同步 则需要在请求之前进行集合点的设置 具体位置在 添加 定时器 Synchronizing Timer 同步定时器
  • 01-LED-Blink-Demo(开发环境esp-idf)

    Blink Example This example code is in the Public Domain or CC0 licensed at your option Unless required by applicable law
  • 使用 STM32 的 SPI 来读取外部 SPI FLASH 芯片(W25Qxx)

    SPI简介 SPI 是英语 Serial Peripheral interface 的缩写 顾名思义就是串行外围设备接口 是 Motorola 首先在其 MC68HCXX 系列处理器上定义的 SPI 接口主要应用在 EEPROM FLASH
  • LeetCode刷题笔记:1619.删除某些元素后的数组均值

    1 问题描述 给你一个整数数组 arr 请你删除最小 5 的数字和最大 5 的数字后 剩余数字的平均值 与 标准答案 误差在 10 5 的结果都被视为正确结果 2 解题思路 先排序 再从数组下标5 处开始遍历 到数组下标95 截止 3 代码
  • 设计模式1:单例模式、工厂、创建者、原型

    设计模式 一种抽象 总结 Gang of Four GOF 分类 3大类23种 创建型模式 结构型模式和行为型模式 几个设计原则 接口分离 依赖倒置 原则 编程面向接口而不是实现 单一原则 单一部分完成特定的分类功能 封装 开闭原则 对修改
  • Ubuntu14/16 PCL1.7/1.8 opencv2/3/4 编译安装共存

    为了使用cuda和pcl共同编程 而系统带的pcl1 7不带gpu模块 故编译安装pcl完全版 与系统pcl1 7共存 不同分发版本Ubuntu应该没有什么区别 不同版本pcl编译和使用道理也都基本相同 opencv也是一样的道理 PCL
  • 嵌入式系统原理及应用(基于STM32)救急专用

    目录 第一章 嵌入式系统概述 第二章 嵌入式系统基础知识 第三章 STM32系列微控制器 第四章 通用输入输出端口 第五章 异常与中断处理 第六章 定时器 第七章 串行通信接口 第八章 模数转换器 数模转换器 第一章 嵌入式系统概述 嵌入式
  • 剑指offer.13.机器人的运动范围之DFS、BFS搜索

    机器人的运动范围 前言 一 DFS 1 思想 2 源码 二 BFS 1 源码 2 改进源码BFS 总结 前言 对于矩阵搜索问题 就像图的搜索一样 熟练掌握DFS BFS是关键 一 DFS 1 思想 通过DFS去寻找满足条件的格子 而已经访问