立志用最少的代码做最高效的表达


题目

地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

示例 1:
输入:m = 2, n = 3, k = 1
输出:3

示例 2:
输入:m = 3, n = 1, k = 0
输出:1

提示:
1 <= n,m <= 100
0 <= k <= 20


文章目录

  • 题目
  • 第一次解题
  • 第二次解题
  • 第三次优化
  • 第四次优化
  • 完整可运行代码

第一次解题

错误解法:直接遍历二维数组试图解题,发现出错,因为机器人无法越过障碍

class Solution {public int movingCount(int m, int n, int k) {int num1, num2, sum = 0;for(int i = 0; i < m; i++) {for(int j = 0; j < n; j++) {num1 = 0; num2 = 0;int ii = i, jj = j;while(ii != 0) { num1 += ii%10; ii/= 10; }while(jj != 0) { num2 += jj%10; jj/= 10; }if(num1 + num2 <= k) sum++;System.out.println(i + "  " + j + "  " + num1 + "  " + num2 + "  " + sum);}}return sum;}
}

第二次解题

仔细思考后发现,这是一道考查连通块的题,即连通(0,0)的点的个数。
于是用DFS解,如下:

static class Solution {boolean[][] vis;int sum;int kk; // 代替k,定义全局变量,可以为dfs方法减少一个参数int[][] next;int mm, nn;public int movingCount(int m, int n, int k) {// 全局变量的定义vis = new boolean[m][n];sum = 1;    // (0,0)一定能被访问到kk = k;  mm = m; nn = n;next = new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}};vis[0][0] = true;dfs(0, 0);return sum;}public void dfs(int x, int y) {// 终止条件if(x > mm || y > nn) return;// 回溯for(int i = 0; i < 4; i++) {int xx = x + next[i][0], yy = y + next[i][1];// 1、超界, continueif(xx < 0 || xx >= mm || yy < 0 || yy >= nn) continue;// 2、被访问过,continueif(vis[xx][yy]) continue;// 3、计算是否能到达int xx1 = xx, yy1 = yy;int num1 = 0, num2 = 0;while(xx1 != 0) { num1 += xx1%10; xx1 /= 10; }while(yy1 != 0) { num2 += yy1%10; yy1 /= 10; }if(num1 + num2 <= kk) {   // 符合vis[xx][yy] = true;sum++;dfs(xx, yy);}}}
}

第三次优化

解法2中考虑了m或n是100的情况,但即使m or n为100,k最大值也只能取到20,因此不满足条件。 因此只需考虑m or n是二位数的情况即可。

class Solution {boolean[][] vis;int sum;int kk; // 代替k,定义全局变量,可以为dfs方法减少一个参数int[][] next;int mm, nn;public int movingCount(int m, int n, int k) {// 全局变量的定义vis = new boolean[m][n];sum = 1;    // (0,0)一定能被访问到kk = k;  mm = m; nn = n;next = new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}};vis[0][0] = true;dfs(0, 0);return sum;}public void dfs(int x, int y) {// 终止条件if(x > mm || y > nn) return;// 回溯for(int i = 0; i < 4; i++) {int xx = x + next[i][0], yy = y + next[i][1];// 1、是否超界 or 是否满足条件, continueif(xx < 0 || xx >= mm || yy < 0 || yy >= nn || (xx%10 + xx/10 + yy%10 + yy/10 > kk)) continue;// 2、是否曾经走过这个点if(!vis[xx][yy]) {vis[xx][yy] = true;sum++;dfs(xx, yy);}}}
}

第四次优化

第三次优化中,考虑的机器人从上下左右四个方向走的问题,但仔细思考后发现:
由于从0,0开始,因此只考虑向右or向下走即可。

class Solution {boolean[][] vis;int sum;int kk; // 代替k,定义全局变量,可以为dfs方法减少一个参数int[][] next;int mm, nn;public int movingCount(int m, int n, int k) {// 全局变量的定义vis = new boolean[m][n];sum = 1;    // (0,0)一定能被访问到kk = k;  mm = m; nn = n;next = new int[][]{{1,0}, {0,1}};vis[0][0] = true;dfs(0, 0);return sum;}public void dfs(int x, int y) {// 终止条件if(x > mm || y > nn) return;// 回溯for(int i = 0; i < 2; i++) {int xx = x + next[i][0], yy = y + next[i][1];// 1、是否超界 or 是否满足条件, continueif(xx < 0 || xx >= mm || yy < 0 || yy >= nn || (xx%10 + xx/10 + yy%10 + yy/10 > kk)) continue;// 2、是否曾经走过这个点if(!vis[xx][yy]) {vis[xx][yy] = true;sum++;dfs(xx, yy);}}}
}

完整可运行代码

最后附上完整可运行代码

public class 剑指Offer13_机器人的运动范围 {// 错误解法: 因为无法越过障碍static class Solution_1 {public int movingCount(int m, int n, int k) {int num1, num2, sum = 0;for(int i = 0; i < m; i++) {for(int j = 0; j < n; j++) {num1 = 0; num2 = 0;int ii = i, jj = j;while(ii != 0) { num1 += ii%10; ii/= 10; }while(jj != 0) { num2 += jj%10; jj/= 10; }if(num1 + num2 <= k) sum++;System.out.println(i + "  " + j + "  " + num1 + "  " + num2 + "  " + sum);}}return sum;}}// 解法2:dfs:本质上是求连通块,就是连通(0,0)点的所有点的个数Sstatic class Solution_2 {boolean[][] vis;int sum;int kk; // 代替k,定义全局变量,可以为dfs方法减少一个参数int[][] next;int mm, nn;public int movingCount(int m, int n, int k) {// 全局变量的定义vis = new boolean[m][n];sum = 1;    // (0,0)一定能被访问到kk = k;  mm = m; nn = n;next = new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}};vis[0][0] = true;dfs(0, 0);return sum;}public void dfs(int x, int y) {// 终止条件if(x > mm || y > nn) return;// 回溯for(int i = 0; i < 4; i++) {int xx = x + next[i][0], yy = y + next[i][1];// 1、超界, continueif(xx < 0 || xx >= mm || yy < 0 || yy >= nn) continue;// 2、被访问过,continueif(vis[xx][yy]) continue;// 3、计算是否能到达int xx1 = xx, yy1 = yy;int num1 = 0, num2 = 0;while(xx1 != 0) { num1 += xx1%10; xx1 /= 10; }while(yy1 != 0) { num2 += yy1%10; yy1 /= 10; }if(num1 + num2 <= kk) {   // 符合vis[xx][yy] = true;sum++;dfs(xx, yy);}}}}// 解法2中考虑的m或n是100的情况,但即使m or n为100,k最大值也只能取到20,因此不满足条件。  因此只需考虑m or n是二位数的情况即可。static class Solution_3 {boolean[][] vis;int sum;int kk; // 代替k,定义全局变量,可以为dfs方法减少一个参数int[][] next;int mm, nn;public int movingCount(int m, int n, int k) {// 全局变量的定义vis = new boolean[m][n];sum = 1;    // (0,0)一定能被访问到kk = k;  mm = m; nn = n;next = new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}};vis[0][0] = true;dfs(0, 0);return sum;}public void dfs(int x, int y) {// 终止条件if(x > mm || y > nn) return;// 回溯for(int i = 0; i < 4; i++) {int xx = x + next[i][0], yy = y + next[i][1];// 1、是否超界 or 是否满足条件, continueif(xx < 0 || xx >= mm || yy < 0 || yy >= nn || (xx%10 + xx/10 + yy%10 + yy/10 > kk)) continue;// 2、是否曾经走过这个点if(!vis[xx][yy]) {vis[xx][yy] = true;sum++;dfs(xx, yy);}}}}// 解法4:由于从0,0开始,因此只考虑向右or向下走即可。static class Solution_4 {boolean[][] vis;int sum;int kk; // 代替k,定义全局变量,可以为dfs方法减少一个参数int[][] next;int mm, nn;public int movingCount(int m, int n, int k) {// 全局变量的定义vis = new boolean[m][n];sum = 1;    // (0,0)一定能被访问到kk = k;  mm = m; nn = n;next = new int[][]{{1,0}, {0,1}};vis[0][0] = true;dfs(0, 0);return sum;}public void dfs(int x, int y) {// 终止条件if(x > mm || y > nn) return;// 回溯for(int i = 0; i < 2; i++) {int xx = x + next[i][0], yy = y + next[i][1];// 1、是否超界 or 是否满足条件, continueif(xx < 0 || xx >= mm || yy < 0 || yy >= nn || (xx%10 + xx/10 + yy%10 + yy/10 > kk)) continue;// 2、是否曾经走过这个点if(!vis[xx][yy]) {vis[xx][yy] = true;sum++;dfs(xx, yy);}}}}public static void main(String[] args) {Solution_2 solution_2 = new Solution_2();System.out.println(solution_2.movingCount(16, 8, 4));}
}

【四重优化,速看】剑指 Offer 13. 机器人的运动范围相关推荐

  1. LeetCode 剑指Offer 13 机器人的运动范围

    LeetCode 剑指Offer 13 机器人的运动范围 题目 解题 解题一:深度优先搜索 解题二:广度优先搜索 解题三:动态规划 题目 解题 深度优先和广度优先解题思路参考: 剑指 Offer 13 ...

  2. 【LeetCode】剑指 Offer 13. 机器人的运动范围

    [LeetCode]剑指 Offer 13. 机器人的运动范围 文章目录 [LeetCode]剑指 Offer 13. 机器人的运动范围 package offer;public class Solu ...

  3. 剑指 Offer 13. 机器人的运动范围

    剑指 Offer 13. 机器人的运动范围 题目 ​ 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] .一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左.右.上 ...

  4. [[EVD]] - 剑指 Offer 13. 机器人的运动范围

    题目分析:[[EVD]] - 剑指 Offer 13. 机器人的运动范围https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-l ...

  5. Leetcode 剑指 Offer 13. 机器人的运动范围 (每日一题 20210906)

    地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] .一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左.右.上.下移动一格(不能移动到方格外),也不能进入行坐标和列 ...

  6. 剑指 Offer 13. 机器人的运动范围 【重刷】

    文章目录 1.概述 2. 代码 1.概述 题目:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/ 地上有一个m行 ...

  7. 每日一道Leetcode - 剑指 Offer 13. 机器人的运动范围【DFS|BFS】

    DFS: Python版本 class Solution:def movingCount(self, m: int, n: int, k: int) -> int:def dfs(i,j,si, ...

  8. Leetcode刷题笔记——剑指 Offer 13. 机器人的运动范围(中等)

    文章目录 题目描述 解题思路 方法一:深度优先遍历DFS 复杂度分析 C++代码实现 方法二:广度优先遍历BFS 复杂度分析 C++代码实现 参考连接 题目描述 地上有一个m行n列的方格,从坐标 [0 ...

  9. 35. (★DFS)剑指 Offer 13. 机器人的运动范围

    题目描述: 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] .一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左.右.上.下移动一格(不能移动到方格外),也不能进 ...

最新文章

  1. apache限制php上传大小修改
  2. HBase架构:HLog region store memstore compact storefile
  3. C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究
  4. python 连通区域_python skimage 连通性区域检测方法
  5. python迭代器是什么百度百科,python迭代器的接口是什么?
  6. Windows下svn服务器安装
  7. Win32 SDK消息处理技巧
  8. INITRANS和MAXTRANS参数的作用
  9. 如何在多个SQL Server上执行作业
  10. 10份数据中台资料分享(附下载)
  11. java构造函数的执行顺序,java构造函数和初始化函数的执行顺序
  12. 【每日算法Day 99】你们可能不知道只用20万赢到578万是什么概念
  13. 一页纸搞定项目管理:定义、要素及操作步骤(附可编辑模板及电子书)
  14. java架构师之路-并发编程
  15. 我奋斗了18年不是为了和你一起喝咖啡。
  16. vue switch组件
  17. 累加器 java_Spark笔记之累加器(Accumulator)
  18. 【中序、后序遍历序列】【前序、中序遍历序列】构造二叉树
  19. 地下水位监测预警方案 | 助力城市排水信息化
  20. 初读犀牛书------第一天

热门文章

  1. PyCairo 中的变换
  2. 浅谈 FTP、FTPS 与 SFTP
  3. 从新冠疫情出发,漫谈 Gossip 协议
  4. 80%的Linux都不懂的内存问题
  5. 面试官:为什么SpringBoot的 jar 可以直接运行?
  6. Java开发必须掌握的 20+ 种 Spring 常用注解
  7. 压箱底总结:流系统端到端一致性对比
  8. 什么是 Go runtime.KeepAlive?
  9. GRTN赋能淘系内容业务的演进路线及未来规划
  10. 周小鹏:努力让FPGA支持更多开源库和框架