{x}
blog image

Android Unlock Patterns

Solution Explanation for Android Unlock Patterns

This problem asks to find the number of valid unlock patterns of length at least m and at most n on a 3x3 grid. A pattern is valid if:

  1. All dots are distinct.
  2. If a line segment between two consecutive dots passes through the center of another dot, that dot must have already been used in the pattern.

Approach

The solution uses Depth-First Search (DFS) with backtracking and a clever optimization to avoid redundant computations.

1. cross array: This 10x10 array stores the "jump-over" information. cross[i][j] represents the dot that lies between dot i and dot j if such a dot exists. If no dot lies between i and j, the value is 0.

2. dfs(i, cnt) function: This is the recursive DFS function.

  • i: The index of the current dot being considered (1-9).
  • cnt: The length of the current pattern.
  • It marks the current dot i as visited (vis[i] = true).
  • If the pattern length (cnt) is within the allowed range (m to n), it adds 1 to the count of valid patterns.
  • It iterates through all dots (1-9). If a dot j is not visited and the condition for passing through the center is met (cross[i][j] == 0 or vis[cross[i][j]]), it recursively calls dfs(j, cnt + 1).
  • After exploring all possibilities from the current dot, it unmarks it (vis[i] = false) to backtrack.

3. Symmetry Optimization: The solution leverages symmetry to reduce computations. Instead of exploring all possible starting points (1-9), it only explores three: 1, 2, and 5.

  • Starting from 1: Patterns starting from 1, 3, 7, and 9 are symmetric.
  • Starting from 2: Patterns starting from 2, 4, 6, and 8 are symmetric.
  • Starting from 5: Patterns starting from 5 are unique.

The total number of unique patterns is calculated as dfs(1, 1) * 4 + dfs(2, 1) * 4 + dfs(5, 1).

Time and Space Complexity

  • Time Complexity: O(N), where N is the number of possible valid patterns. Although it appears exponential at first glance due to the recursion, the pruning from the cross array and symmetry dramatically reduces the number of explored paths. The number of possible patterns is far less than the theoretical maximum (9!).

  • Space Complexity: O(1). The cross array and vis array are of constant size. The recursive call stack's depth is at most 9 (maximum pattern length).

Code in Different Languages

The code implementations in Python, Java, C++, Go, and TypeScript are provided in the problem description. They all follow the same algorithm described above. The differences are mostly syntactical.