Android Unlock Patterns

204 篇文章 0 订阅

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.
android unlock

这里写图片描述
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.

样例
Given m = 1, n = 1, return 9.

思路

| 1 | 2 | 3 |
| 4 | 5 | 6 |
| 7 | 8 | 9 |
对于上述键盘,总结出如下规则:
1、7需要中间键4,2、8需要中间键5,3、9需要中间键6,
1、3需要中间键2,4、6需要中间键5,7、9需要中间键8,
1、9和3、7需要中间键5(包括相反的情况1、9–>9、1)
其余情况均不需要中间的键值(困惑在于2,7之间也不需要)。
之后,深度遍历一个键值,得到它能够成的最多图案数。由于键盘的对称性,1,3,7,9得到的图案数相同,2,4,6,8得到的图案数相同,5单独计算。

#ifndef C909_H
#define C909_H
#include<iostream>
#include<vector>
using namespace std;
class Solution {
public:
    int numberOfPatterns(int m, int n) {
        int res = 0;
        vector<bool> visited(10, false);
        vector<vector<int>> keyboard(10, vector<int>(10, 0));//keyboard[i][j]表示从i跳转到j中间需要键值
        //根据规则初始化跳转矩阵的键值
        keyboard[1][3] = keyboard[3][1] = 2;
        keyboard[4][6] = keyboard[6][4] = 5;
        keyboard[7][9] = keyboard[9][7] = 8;
        keyboard[1][7] = keyboard[7][1] = 4;
        keyboard[2][8] = keyboard[8][2] = 5;
        keyboard[3][9] = keyboard[9][3] = 6;
        keyboard[1][9] = keyboard[9][1] = keyboard[3][7] = keyboard[7][3] = 5;
        //由对称性可得,1,3,7,9值相同;2,4,6,8值相同;5独自求值
        res += helper(1, 1, m, n, keyboard, visited) * 4;
        res += helper(2, 1, m, n, keyboard, visited) * 4;
        res += helper(5, 1, m, n, keyboard, visited);
        return res;
    }
    //从num开始深度遍历跳转矩阵keyboard
    //遍历1~9,找出可以直接到达的键和中间键已经被访问的键,添加到最终结果
    int helper(int num, int len, int m, int n, vector<vector<int>> &keyboard, vector<bool> visited)
    {
        int res = 0;
        if (len >= m)
            res++;
        ++len;
        if (len > n)
            return res;
        visited[num] = true;
        for (int i = 1; i <= 9; ++i)
        {
            int mid = keyboard[num][i];
            if (!visited[i] && (mid == 0 || visited[mid]))
            {
                res += helper(i, len, m, n, keyboard, visited);
            }
        }
        visited[num] = false;
        return res;
    }
};
#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值