|
| 1 | +/** |
| 2 | + * 351. Android Unlock Patterns |
| 3 | + * https://leetcode.com/problems/android-unlock-patterns/ |
| 4 | + * Difficulty: Medium |
| 5 | + * |
| 6 | + * Android devices have a special lock screen with a 3 x 3 grid of dots. Users can set an |
| 7 | + * "unlock pattern" by connecting the dots in a specific sequence, forming a series of joined |
| 8 | + * line segments where each segment's endpoints are two consecutive dots in the sequence. |
| 9 | + * A sequence of k dots is a valid unlock pattern if both of the following are true: |
| 10 | + * - All the dots in the sequence are distinct. |
| 11 | + * - If the line segment connecting two consecutive dots in the sequence passes through the |
| 12 | + * center of any other dot, the other dot must have previously appeared in the sequence. |
| 13 | + * No jumps through the center non-selected dots are allowed. |
| 14 | + * - For example, connecting dots 2 and 9 without dots 5 or 6 appearing beforehand is valid |
| 15 | + * because the line from dot 2 to dot 9 does not pass through the center of either dot 5 or 6. |
| 16 | + * - However, connecting dots 1 and 3 without dot 2 appearing beforehand is invalid because |
| 17 | + * the line from dot 1 to dot 3 passes through the center of dot 2. |
| 18 | + * |
| 19 | + * Here are some example valid and invalid unlock patterns: |
| 20 | + */ |
| 21 | + |
| 22 | +/** |
| 23 | + * @param {number} m |
| 24 | + * @param {number} n |
| 25 | + * @return {number} |
| 26 | + */ |
| 27 | +var numberOfPatterns = function(m, n) { |
| 28 | + const jumps = new Array(10).fill().map(() => new Array(10).fill(0)); |
| 29 | + jumps[1][3] = jumps[3][1] = 2; |
| 30 | + jumps[1][7] = jumps[7][1] = 4; |
| 31 | + jumps[3][9] = jumps[9][3] = 6; |
| 32 | + jumps[7][9] = jumps[9][7] = 8; |
| 33 | + jumps[1][9] = jumps[9][1] = jumps[2][8] = jumps[8][2] = jumps[3][7] |
| 34 | + = jumps[7][3] = jumps[4][6] = jumps[6][4] = 5; |
| 35 | + |
| 36 | + function backtrack(current, visited, length) { |
| 37 | + if (length > n) return 0; |
| 38 | + let count = length >= m ? 1 : 0; |
| 39 | + if (length === n) return count; |
| 40 | + |
| 41 | + for (let next = 1; next <= 9; next++) { |
| 42 | + if (!visited.has(next)) { |
| 43 | + const jump = jumps[current][next]; |
| 44 | + if (jump === 0 || visited.has(jump)) { |
| 45 | + visited.add(next); |
| 46 | + count += backtrack(next, visited, length + 1); |
| 47 | + visited.delete(next); |
| 48 | + } |
| 49 | + } |
| 50 | + } |
| 51 | + return count; |
| 52 | + } |
| 53 | + |
| 54 | + let total = 0; |
| 55 | + const visited = new Set(); |
| 56 | + visited.add(1); |
| 57 | + total += backtrack(1, visited, 1) * 4; |
| 58 | + visited.delete(1); |
| 59 | + |
| 60 | + visited.add(2); |
| 61 | + total += backtrack(2, visited, 1) * 4; |
| 62 | + visited.delete(2); |
| 63 | + |
| 64 | + visited.add(5); |
| 65 | + total += backtrack(5, visited, 1); |
| 66 | + |
| 67 | + return total; |
| 68 | +}; |
0 commit comments