Android Unlock Patterns

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:

  1. Each pattern must connect at least m keys and at most n keys.
  2. All the keys must be distinct.
  3. 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.
  4. 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:

Input: m = 1, n = 1
Output: 9

思路:中間不能有間隔點,那麼我們用一個skip矩陣首先去記錄這種關係,然後發現1,3,7,9 是對稱的,是一個group,2,4,6,8也是對稱的,是一種group,5是另外一種group

剩下的就是backtracking,dfs

訪問next point,確保next point沒有被訪問過,而且中間不能有skip點或者skip點已經被訪問過了,那麼就可以繼續計算;

class Solution {
    public int numberOfPatterns(int m, int n) {
        int[][] skip = new int[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[7][3] = skip[3][7] = skip[2][8] = skip[8][2] = skip[4][6] = skip[6][4] = 5;
        boolean[] visited = new boolean[10];
        int res = 0;
        for(int i = m; i <= n; i++) {
            // 1,3,7,9 is one group,they are the same;
            // 2,4,6,8 is one group, they are the same;
            // 5 is group;
            res += dfs(visited, skip, 1, i - 1) * 4;
            res += dfs(visited, skip, 2, i - 1) * 4;
            res += dfs(visited, skip, 5, i - 1) * 1;
        }
        return res;
    }
    
    private int dfs(boolean[] visited, int[][] skip, int cur, int remain) {
        if(remain < 0) return 0;
        if(remain == 0) return 1;
        visited[cur] = true;
        int res = 0;
        for(int i = 1; i <= 9; i++) {
            // 接下來的點沒有訪問過,而且要麼沒有skip point,要麼skip point被訪問過了,那麼就繼續計算;
            if(!visited[i] && (skip[cur][i] == 0 || visited[skip[cur][i]])) {
                res += dfs(visited, skip, i, remain - 1);
            }
        }
        visited[cur] = false;
        return res;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章