android 解锁,规则比较复杂,其中比较复杂的是
1) 从1 到3, 如果要穿越2, 那么2必须已经走过了
| 1 | 2 | 3 | | 4 | 5 | 6 | | 7 | 8 | 9 |
2) 这样一个九宫格, 定义里竟然1 可以直接到8 的, 不在“穿越” 的定义里!
直接看穿越的定义: 把穿越的关系 定义在一个 二维数组中, 这是这题比较巧妙地地方, 比如 1 -->3 中间为2, 那么只要 看 visted[steps[1][3]] = visted[2] 是否被访问过即可。
steps[1][3] = steps[3][1] = 2; steps[1][7] = steps[7][1] = 4; steps[3][9] = steps[9][3] = 6; steps[7][9] = steps[9][7] = 8; steps[1][9] = steps[2][8] = steps[4][6] = steps[3][7] = 5; steps[9][1] = steps[8][2] = steps[6][4] = steps[7][3] = 5;
分析: 1,3,7,9 是对称的, 2,4,6,8 也是对称的, 5是单独的, 因此只要从 1,3,7,9 中选 1 ,结果 x4, 从 2,4,6,8 中选2 结果x4。 最后结果就是 dfs(1) *4 + dfs(2) *4 + dfs(5)
tip1 :
给定的 m, n 是一个范围, 在dfs 里直接写不好写, 所以用一个for 循环 调用 dfs 函数, 保证每次深度就一个而不是一个范围。
tip2: 注意起始深度是1, 而不是0, 也就是
dfs(1,1,len,visted,steps)
因为起点已经算放置一个点了,所起始深度为1.
tip3:
这三行 :
depth++; count+= dfs(i,depth, length,visted,steps); depth --
可以直接等于 : count+= dfs(i,depth+1, length,visted,steps); 注意不能是 count+= dfs(i,depth++, length,visted,steps);
递归数: 注意 第一个节点时已经是 depth =1 了。
class Solution { public int numberOfPatterns(int m, int n) { final int DOTS = 10; int[][] steps = new int[DOTS][DOTS]; steps[1][3] = steps[3][1] = 2; steps[1][7] = steps[7][1] = 4; steps[3][9] = steps[9][3] = 6; steps[7][9] = steps[9][7] = 8; steps[1][9] = steps[2][8] = steps[4][6] = steps[3][7] = 5; steps[9][1] = steps[8][2] = steps[6][4] = steps[7][3] = 5; boolean[] visted = new boolean[DOTS]; visted[0] = true; // 剩下的所有steps 都可以直接到达, 注意1-->8 是可以直接穿越的。 int count = 0; for(int len = m; len<=n; len++){ count += 4* dfs(1,1,len,visted,steps) + 4* dfs(2,1,len,visted,steps) + dfs(5,1,len,visted,steps); } return count; } private int dfs( int start,int depth, int length, boolean[] visted,int[][] steps){ int count=0; if(depth == length) { return 1; } if(depth >length) return 0; visted[start] = true; for(int i =1; i<=9; i++){ if(!visted[i] && visted[steps[start][i]] ){ // i 没有被访问, 且 visted[穿越] 已经被访问了 depth++; count+= dfs(i,depth, length,visted,steps); depth --; } } visted[start] = false; return count; } }
那如果不用 for 循环, 直接给dfs 里传 m, n的写法:
tip: 得在 这个条件里直接 count++, 不能在这里return, return 的条件只能是 depth >n
if(depth >=m && depth<=n) count++;
class Solution { public int numberOfPatterns(int m, int n) { final int DOTS = 10; int[][] steps = new int[DOTS][DOTS]; steps[1][3] = steps[3][1] = 2; steps[1][7] = steps[7][1] = 4; steps[3][9] = steps[9][3] = 6; steps[7][9] = steps[9][7] = 8; steps[1][9] = steps[2][8] = steps[4][6] = steps[3][7] = 5; steps[9][1] = steps[8][2] = steps[6][4] = steps[7][3] = 5; boolean[] visted = new boolean[DOTS]; visted[0] = true; // 剩下的所有steps 都可以直接到达, 注意1-->8 是可以直接穿越的。 return 4* dfs(1,1,m,n,visted,steps) + 4* dfs(2,1,m,n,visted,steps) + dfs(5,1,m,n,visted,steps); } private int dfs( int start,int depth, int m, int n, boolean[] visted,int[][] steps){ int count = 0; if(depth >n) return count; if(depth >=m && depth<=n) count++; visted[start] = true; for(int i =1; i<=9; i++){ if(!visted[i] && visted[steps[start][i]] ) // i 没有被访问, 且 visted[穿越] 已经被访问了 count += dfs(i,depth+1, m,n,visted,steps); } visted[start] = false; return count; } }