本文主要是介绍手机的九宫格图案解锁总共能绘出多少种图案?LeetCode 351. Android Unlock Patterns,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
需要满足的要求有:
至少经过四个点;
不能重复经过同一个点;
路径上的中间点不能跳过(如从1到3一定会经过2);
如果中间的点是之前已经用过的,那么这个点就可以被跳过(如213,因为2已经被用过,1就可以越过2与3连接,132是不允许的)。
作者:linkwun
链接:https://www.zhihu.com/question/24905007/answer/29414497
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
from itertools import chain, permutationsimpossible = {'13': '2', '46': '5', '79': '8', '17': '4', '28': '5', '39': '6', '19': '5', '37': '5','31': '2','64': '5','97': '8','71': '4','82': '5','93': '6','91': '5','73': '5'}def counts():iterlst = chain(*(permutations('123456789', i) for i in range(4, 10)))count = 0for i in iterlst:stri = ''.join(i)for k, v in impossible.items():if k in stri and v not in stri[:stri.find(k)]:breakelse:count += 1return countprint(counts())#389112
我用python写了段代码,先计算出所有大于四个数字的所有排列组合,然后从中剃除穿过中间那个数字的组合,剩下的既为符合要求的代码。
例如13组合是不可能存在的,因为它会穿过2,19组合也不可能存在,因为它会穿过5,总共有16个这样的组合。
但是假如中间这个数字已经用过了,是可以穿过的,比如213,2已经用过了,1是可以穿过2与3连接的。
如此筛选以后,就得到正确答案389112了。
以下两段codes可以看做是等价的,只是chain的效率更高:
iterlst = chain(*(permutations('123456789', i) for i in range(4, 10)))count = 0for i in iterlst:
和
for permutation in ((permutations('123456789', i) for i in range(4, 10))):for item in permutation:print(item)
后记:上面的解法并不够通用,通用的解法就是回溯。回溯需要注意两点:
1. 回溯过程中无非考虑相邻两个节点之间的关系,同时满足两个条件为合法:
a. 并没有访问过
b. (存在13这种跨越,但是2已经被访问过了)或者不存在13这种跨越,这些跨越打个表就好
2. 利用对称性优化
最后贴一下leetcode 的题目和codes:
----------------------------------------------
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:
- Each pattern must connect at least m keys and at most n keys.
- All the keys must be distinct.
- 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.
- 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
----------------------------------------------
class Solution:def numberOfPatterns(self, m, n):cross = {(1,3):2,(3,1):2,(1,7):4,(7,1):4,(3,9):6,(9,3):6,(7,9):8,(9,7):8,(1,9):5,(9,1):5,(2,8):5,(8,2):5,(3,7):5,(7,3):5,(4,6):5,(6,4):5}visited = set()def dfs(x, k):if not k: return 1visited.add(x)cnt = sum(dfs(y, k-1) for y in range(1,10) if y not in visited and ((x,y) not in cross or ((x,y) in cross and cross[(x,y)] in visited)))visited.discard(x)return cntreturn sum(dfs(1,k)*4 + dfs(2,k)*4 + dfs(5,k) for k in range(m-1, n))
这篇关于手机的九宫格图案解锁总共能绘出多少种图案?LeetCode 351. Android Unlock Patterns的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!