【四重优化,速看】剑指 Offer 13. 机器人的运动范围
立志用最少的代码做最高效的表达
题目
地上有一个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. 机器人的运动范围相关推荐
- LeetCode 剑指Offer 13 机器人的运动范围
LeetCode 剑指Offer 13 机器人的运动范围 题目 解题 解题一:深度优先搜索 解题二:广度优先搜索 解题三:动态规划 题目 解题 深度优先和广度优先解题思路参考: 剑指 Offer 13 ...
- 【LeetCode】剑指 Offer 13. 机器人的运动范围
[LeetCode]剑指 Offer 13. 机器人的运动范围 文章目录 [LeetCode]剑指 Offer 13. 机器人的运动范围 package offer;public class Solu ...
- 剑指 Offer 13. 机器人的运动范围
剑指 Offer 13. 机器人的运动范围 题目 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] .一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左.右.上 ...
- [[EVD]] - 剑指 Offer 13. 机器人的运动范围
题目分析:[[EVD]] - 剑指 Offer 13. 机器人的运动范围https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-l ...
- Leetcode 剑指 Offer 13. 机器人的运动范围 (每日一题 20210906)
地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] .一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左.右.上.下移动一格(不能移动到方格外),也不能进入行坐标和列 ...
- 剑指 Offer 13. 机器人的运动范围 【重刷】
文章目录 1.概述 2. 代码 1.概述 题目:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/ 地上有一个m行 ...
- 每日一道Leetcode - 剑指 Offer 13. 机器人的运动范围【DFS|BFS】
DFS: Python版本 class Solution:def movingCount(self, m: int, n: int, k: int) -> int:def dfs(i,j,si, ...
- Leetcode刷题笔记——剑指 Offer 13. 机器人的运动范围(中等)
文章目录 题目描述 解题思路 方法一:深度优先遍历DFS 复杂度分析 C++代码实现 方法二:广度优先遍历BFS 复杂度分析 C++代码实现 参考连接 题目描述 地上有一个m行n列的方格,从坐标 [0 ...
- 35. (★DFS)剑指 Offer 13. 机器人的运动范围
题目描述: 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] .一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左.右.上.下移动一格(不能移动到方格外),也不能进 ...
最新文章
- apache限制php上传大小修改
- HBase架构:HLog region store memstore compact storefile
- C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究
- python 连通区域_python skimage 连通性区域检测方法
- python迭代器是什么百度百科,python迭代器的接口是什么?
- Windows下svn服务器安装
- Win32 SDK消息处理技巧
- INITRANS和MAXTRANS参数的作用
- 如何在多个SQL Server上执行作业
- 10份数据中台资料分享(附下载)
- java构造函数的执行顺序,java构造函数和初始化函数的执行顺序
- 【每日算法Day 99】你们可能不知道只用20万赢到578万是什么概念
- 一页纸搞定项目管理:定义、要素及操作步骤(附可编辑模板及电子书)
- java架构师之路-并发编程
- 我奋斗了18年不是为了和你一起喝咖啡。
- vue switch组件
- 累加器 java_Spark笔记之累加器(Accumulator)
- 【中序、后序遍历序列】【前序、中序遍历序列】构造二叉树
- 地下水位监测预警方案 | 助力城市排水信息化
- 初读犀牛书------第一天