地上有一个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
思路
刚开始做这题的时候,还以为只要计算二维数组中每个坐标点的数位和是否<=k即可,结果预期输出15,我输出了25。
后来一想,可能会出现一整行或者一整列的坐标点数位和都>k的情况,此时路径就被完全拦断,之后的点也到不了,所以,还是得用DFS来模拟机器人走路。
这题的大致想法就是让机器人从[0, 0]
处开始,朝上下左右四个方向走,判断能否到达的条件就是:
- 不越界;
- 数位和小于等于k;
- 未被访问过(这是为了防止走重复的路)。
总之,这题就是很简单的一道DFS。但是因为用JAVA写还是受了不少苦,主要是以下几个方面:
- 关于JAVA中传值和传地址的问题:JAVA用基本数据类型都是传值,因此,如果想在
dfs
函数里传入可行点数cnt
,则需要将cnt
封装在一个类里面,然后把这个类传入函数才行; - 关于LeetCode在线输出和本地输出不一致的问题:LeetCode应该是实例化一个对象,然后多次调用我们写的这个功能函数去评测(来自:Bollie的回答),所以,写的时候,成员类名、方法名、变量名尽量都不要加上
static
,否则的话,就会导致对象多次调用的时候,使用的都是同一个变量/方法。
代码
public class Solution {
class Count{//java传地址只能用类传,不像C++可以加别名&
int num;
}
int[] dx = {0, 0, -1, 1};
int[] dy = {-1, 1, 0, 0};
boolean[][] visited = new boolean[110][110];
public boolean digitalSum(int x, int y, int k) {//计算当前坐标的数位和
int sum = 0;
String xx = String.valueOf(x);
String yy = String.valueOf(y);
for(int i=0;i<xx.length();i++) {
sum += xx.charAt(i)-48;//ASCII码-48
}
for(int i=0;i<yy.length();i++) {
sum += yy.charAt(i)-48;
}
if(sum<=k) return true;
else return false;
}
public boolean canReach(int x, int y, int m, int n, int k){//判断下一个点可不可达
if(x<0||x>m-1||y<0||y>n-1) {//越界
return false;
}
if(digitalSum(x, y, k)==false) {//数位和大于k
return false;
}
if(visited[x][y]==true) {//已被访问过
return false;
}
return true;
}
public void dfs(int x, int y, int m, int n, int k, Count cnt) {
cnt.num++;
visited[x][y] = true;
for(int i=0;i<4;i++) {
int next_x = x + dx[i];
int next_y = y + dy[i];
if(canReach(next_x, next_y, m, n, k)==true) {
dfs(next_x, next_y, m, n, k, cnt);
}
}
}
public int movingCount(int m, int n, int k) {
Count cnt = new Count();
dfs(0, 0, m, n, k, cnt);
return cnt.num;
}
}