面试题13. 机器人的运动范围【中等】
机器人每次只能移动一格,因此每次只需计算 x 到 x±1 的数位和增量。
数位和增量公式:设x的数位和sxs_xsx,x的数位和sx+1s_{x+1}sx+1
可达解分析:根据数位和增量公式得知,数位和每逢进位突变一次。
因此可以将矩阵分为三个区域,黄色三角形区域内的解虽然满足数位和要求,但由于机器人每步只能走一个单元格,而三角形间不一定是连通的,因此机器人不一定能到达,称为不可达解。可到达的称为可达解。
根据可达解的结构和连通性,易推出机器人可仅通过向右和向下移动,访问所有可达解。
visited
中,代表此单元格已被访问过。class Solution {int row,col,lim;boolean[][] visited;public int movingCount(int m, int n, int k) {row=m;col=n;lim=k;visited=new boolean[m][n];return dfs(0,0,0,0);}public int dfs(int i,int j,int si,int sj){if(i>=row||j>=col||si+sj>lim||visited[i][j])return 0;visited[i][j]=true;int newSi=(i+1)%10==0?si-8:si+1;//(i+1,j)数位和int newSj=(j+1)%10==0?sj-8:sj+1;//(i,j+1)数位和return 1+dfs(i+1,j,newSi,sj)+dfs(i,j+1,si,newSj);}
}
时间复杂度:O(mn)O(mn)O(mn)
空间复杂度:O(mn)O(mn)O(mn)
visited
中,代表此单元格已被访问过。visited
的长度,即可达解的数量。class Solution {public int movingCount(int m, int n, int k) {boolean[][] visited=new boolean[m][n];int res=0;Queuequeue=new LinkedList<>();queue.offer(new int[]{0,0,0,0});while(!queue.isEmpty()){int[] x=queue.poll();int i=x[0],j=x[1],si=x[2],sj=x[3];if(i>=m||j>=n||si+sj>k||visited[i][j])continue;visited[i][j]=true;res++;int newSi=(i+1)%10==0?si-8:si+1;int newSj=(j+1)%10==0?sj-8:sj+1;queue.offer(new int[]{i+1,j,newSi,sj});queue.offer(new int[]{i,j+1,si,newSj});}return res;}
}
时间复杂度:O(mn)O(mn)O(mn)
空间复杂度:O(mn)O(mn)O(mn)