351. 安卓系统手势解锁

我们都知道安卓有个手势解锁的界面,是一个 3 x 3 的点所绘制出来的网格。用户可以设置一个 “解锁模式” ,通过连接特定序列中的点,形成一系列彼此连接的线段,每个线段的端点都是序列中两个连续的点。如果满足以下两个条件,则 k 点序列是有效的解锁模式:

解锁模式中的所有点 互不相同 。
假如模式中两个连续点的线段需要经过其他点,那么要经过的点必须事先出现在序列中(已经经过),不能跨过任何还未被经过的点。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/android-unlock-patterns
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

import java.util.Arrays;

public class Solution {

    private boolean used[] = new boolean[9];

    public int numberOfPatterns(int n, int m) {
        int res = 0;
        for (int len = n; len <= m; len++) {
            res += calcPatterns(-1, len);
            Arrays.fill(used, false);
        }
        return res;
    }

    private boolean isValid(int index, int last) {
        if (used[index])
            return false;
        // first digit of the pattern    
        if (last == -1)
            return true;
        // knight moves or adjacent cells (in a row or in a column)	       
        if ((index + last) % 2 == 1)
            return true;
        // indexes are at both end of the diagonals for example 0,0, and 8,8          
        int mid = (index + last) / 2;
        if (mid == 4)
            return used[mid];
        // adjacent cells on diagonal  - for example 0,0 and 1,0 or 2,0 and //1,1
        if ((index % 3 != last % 3) && (index / 3 != last / 3)) {
            return true;
        }
        // all other cells which are not adjacent
        return used[mid];
    }
    // 0 1 2
    // 3 4 5
    // 6 7 8

    private int calcPatterns(int last, int len) {
        if (len == 0)
            return 1;
        int sum = 0;
        for (int i = 0; i < 9; i++) {
            if (isValid(i, last)) {
                used[i] = true;
                sum += calcPatterns(i, len - 1);
                used[i] = false;
            }
        }
        return sum;
    }
}
上一篇:学习进度(三)


下一篇:351-统计二进制中1的个数