- Notifications
You must be signed in to change notification settings - Fork 123
Expand file tree
/
Copy pathAndroidUnlockPatterns351.java
More file actions
Latest commit
146 lines (129 loc) · 5 KB
/
Copy pathAndroidUnlockPatterns351.java
File metadata and controls
146 lines (129 loc) · 5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/**
* Given an Android 3x3 key lock screen and two integers m and n, where
* 1 ≤ m ≤ n ≤ 9, count the total number of unlock patterns of the Android
* lock screen, which consist of minimum of m keys and maximum n keys.
*
* Rules for a valid pattern:
* - Each pattern must connect at least m keys and at most n keys.
* - All the keys must be distinct.
* - If the line connecting two consecutive keys in the pattern passes through
* any other keys, the other keys must have previously selected in the pattern.
* No jumps through non selected key is allowed.
* - The order of keys used matters.
*
* Explanation:
* | 1 | 2 | 3 |
* | 4 | 5 | 6 |
* | 7 | 8 | 9 |
* Invalid move: 4 - 1 - 3 - 6
* Line 1 - 3 passes through key 2 which had not been selected in the pattern.
*
* Invalid move: 4 - 1 - 9 - 2
* Line 1 - 9 passes through key 5 which had not been selected in the pattern.
*
* Valid move: 2 - 4 - 1 - 3 - 6
* Line 1 - 3 is valid because it passes through key 2, which had been selected in the pattern
*
* Valid move: 6 - 5 - 4 - 1 - 9 - 2
* Line 1 - 9 is valid because it passes through key 5, which had been selected in the pattern.
*
* Example:
* Given m = 1, n = 1, return 9.
*/
publicclassAndroidUnlockPatterns351 {
privateint[][] points = newint[][]{{0,0}, {0,1}, {0,2}, {1,0}, {1,1}, {1,2}, {2,0}, {2,1}, {2,2}};
publicintnumberOfPatterns(intm, intn) {
boolean[][] visited = newboolean[3][3];
// corner
int[] res0 = newint[1];
dfs(visited, 0, 0, m, n, 1, res0);
// edge
int[] res1 = newint[1];
dfs(visited, 0, 1, m, n, 1, res1);
// center
int[] res2 = newint[1];
dfs(visited, 1, 1, m, n, 1, res2);
returnres0[0] * 4 + res1[0] * 4 + res2[0];
}
privatevoiddfs(boolean[][] visited, inti, intj, intm, intn, intlevel, int[] res) {
if (level > n) return;
if (level >= m && level <=n) res[0]++;
visited[i][j] = true;
for (int[] p: points) {
if (!visited[p[0]][p[1]] && canGo(i, j, p[0], p[1], visited)) {
dfs(visited, p[0], p[1], m, n, level+1, res);
}
}
visited[i][j] = false;
}
privatebooleancanGo(inti1, intj1, inti2, intj2, boolean[][] visited) {
if (!isJumping(i1, j1, i2, j2)) returntrue;
returnvisited[(i1+i2)/2][(j1+j2)/2];
}
privatebooleanisJumping(inti1, intj1, inti2, intj2) {
return (i1 == i2 && Math.abs(j1-j2) == 2) ||
(j1 == j2 && Math.abs(i1-i2) == 2) ||
(Math.abs(i1-i2) == 2 && Math.abs(j1-j2) == 2);
}
publicintnumberOfPatterns2(intm, intn) {
// Skip array represents number to skip between two pairs
intskip[][] = newint[10][10];
skip[1][3] = skip[3][1] = 2;
skip[1][7] = skip[7][1] = 4;
skip[3][9] = skip[9][3] = 6;
skip[7][9] = skip[9][7] = 8;
skip[1][9] = skip[9][1] = skip[2][8] = skip[8][2] = skip[3][7] = skip[7][3] = skip[4][6] = skip[6][4] = 5;
booleanvis[] = newboolean[10];
intrst = 0;
// DFS search each length from m to n
for(inti = m; i <= n; ++i) {
rst += DFS(vis, skip, 1, i - 1) * 4; // 1, 3, 7, 9 are symmetric
rst += DFS(vis, skip, 2, i - 1) * 4; // 2, 4, 6, 8 are symmetric
rst += DFS(vis, skip, 5, i - 1); // 5
}
returnrst;
}
// cur: the current position
// remain: the steps remaining
intDFS(booleanvis[], int[][] skip, intcur, intremain) {
if(remain < 0) return0;
if(remain == 0) return1;
vis[cur] = true;
intrst = 0;
for(inti = 1; i <= 9; ++i) {
// If vis[i] is not visited and (two numbers are adjacent or skip number is already visited)
if(!vis[i] && (skip[cur][i] == 0 || (vis[skip[cur][i]]))) {
rst += DFS(vis, skip, i, remain - 1);
}
}
vis[cur] = false;
returnrst;
}
publicintnumberOfPatterns3(intm, intn) {
boolean[][] visited = newboolean[3][3];
int[] res = newint[1];
for (inti=0; i<3; i++) {
for (intj=0; j<3; j++) {
dfs(i, j, visited, m, n, 1, res);
}
}
returnres[0];
}
privatevoiddfs(inti, intj, boolean[][] visited, intm, intn, intlen, int[] res) {
if (visited[i][j] || len > n) return;
if (len >= m) res[0]++;
visited[i][j] = true;
for (intii=0; ii<3; ii++) {
intdi = Math.abs(i - ii);
for (intjj=0; jj<3; jj++) {
intdj = Math.abs(j - jj);
if (di == 0 && dj == 0) continue;
if ((di == 2 && dj != 1) || (dj == 2 && di != 1)) {
if (!visited[(i+ii)/2][(j+jj)/2]) continue;
}
dfs(ii, jj, visited, m, n, len+1, res);
}
}
visited[i][j] = false;
}
}