Given an Android 3x3 key lock screens and integers m and N, where 1≤m≤n≤9, count the total number of unlock Patte RNs of the Android lock screen, which consist of minimum of M keys and maximum n keys.
Rules for a valid pattern:
- Each of the pattern must connect at least m keys and at the most n keys.
- All the keys must is distinct.
- If the line connecting and consecutive keys in the pattern passes through any other keys, the other keys must has Previou Sly selected in the pattern. No jumps through non selected key is allowed.
- 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 isn't been selected in the pattern.
Invalid move:4 - 1 - 9 - 2
Line 1-9 passes through Key 5 which had isn't been selected in the pattern.
Valid move:2 - 4 - 1 - 3 - 6
Line 1-3 are 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 are valid because it passes through key 5, which had been selected in the pattern.
Example:
Given m = 1, n = 1, return 9.
Credits:
Special thanks to @elmirap for adding this problem and creating all test cases.
This problem at first glance the topic so long thought is a design problem, actually not, this question is still more interesting, at least with the actual combination of relatively close. This question is about the unlock method of the Android, there are 9 number keys, if the length of the password range in [m, n] between, ask all the number of unlock modes, pay attention to some illegal sliding patterns given in the topic. So we first look at what is illegal, first 1 can not directly to 3, must go through 2, the same is 4 to 6, 7 to 9, 1 to 7, 2 to 8, 3 to 9, and the diagonal must go through 5, such as 1 to 9, 3 to 7, etc. We set up a two-dimensional array jumps to record whether there are intermediate keys between two numeric keys, and then use an array visited to record whether a key has been accessed, and then we use the recursive solution, we first call the recursive function on 1, in the recursive function, we traverse 1 to 9 each number next, Then find out if there is a jump number between them, and if Next is not visited, and the jump is 0, or if it is visited, we call the recursive function on next. Number 1 mode number calculated, because the 1,3,7,9 is symmetric, so we multiply 4, and then the number 2 to call the recursive function, 2,4,6,9 is also symmetric, then multiply 4, the last individual to 5 call once, and then all add up is the final result, see the code is as follows:
Solution One:
classSolution { Public: intNumberofpatterns (intMintN) {intres =0; Vector<BOOL> Visited (Ten,false); Vector<vector<int>> Jumps (Ten, vector<int> (Ten,0)); jumps[1][3] = jumps[3][1] =2; jumps[4][6] = jumps[6][4] =5; jumps[7][9] = jumps[9][7] =8; jumps[1][7] = jumps[7][1] =4; jumps[2][8] = jumps[8][2] =5; jumps[3][9] = jumps[9][3] =6; jumps[1][9] = jumps[9][1] = jumps[3][7] = jumps[7][3] =5; Res+ = Helper (1,1,0, M, N, jumps, visited) *4; cout<< Res <<Endl; Res+ = Helper (2,1,0, M, N, jumps, visited) *4; cout<< Res <<Endl; Res+ = Helper (5,1,0, M, N, jumps, visited); //cout << res << Endl; returnRes; } intHelperintNumintLenintResintMintN, vector<vector<int>> &jumps, vector<BOOL> &visited) { if(Len >= m) + +Res; ++Len; if(Len > N)returnRes; Visited[num]=true; for(intNext =1; Next <=9; ++next) { intJump =Jumps[num][next]; if(!visited[next] && (jump = =0||Visited[jump])) {Res=Helper (Next, Len, Res, M, N, jumps, visited); }} Visited[num]=false; returnRes; }};
The following method is very concise, but not easy to understand, please see this post. Where used is a 9-bit mask, each digit corresponds to a number, if 1 is present, 0 means not present, (I1, J1) is the previous position, (I, J) is the current position, so the slide is from (I1, J1) to (I, j), the Middle point is ((I1+i)/2, (J1+J)/2 ), where I and J are i1+i and J1+j respectively, and not divided by 2, so I and J are integers. If i%2 or j%2 is not 0, the coordinate of the middle point is not an integer, that is, the middle point does not exist, if the middle point is present, if the middle point is used, then this line is also established, can call recursion, see the code as follows:
Solution Two:
classSolution { Public: intNumberofpatterns (intMintN) {returnCount (M, N,0,1,1); } intCountintMintNintUsed,intI1,intJ1) { intres = M <=0; if(!n)return 1; for(inti =0; I <3; ++i) { for(intj =0; J <3; ++j) {inti = I1 + I, j = J1 + j, Used2 = Used | (1<< (i *3+j)); if(Used2 > Used && (I%2|| J2|| Used2 & (1<< (I/2*3+ J/2))) {res+ = count (M-1N1, Used2, I, J); } } } returnRes; }};
Resources:
Https://leetcode.com/discuss/104320/short-c-solution
Https://leetcode.com/discuss/104436/java-concise-backtracking-solution
Https://leetcode.com/discuss/104688/simple-and-concise-java-solution-in-69ms
Leetcode all in one topic summary (continuous update ...)
[Leetcode] Android Unlock Patterns Android unlock mode