边工作边刷题:70天一遍leetcode: day 94-3
Android Unlock Patterns
要点:
- 本质:递归选下一个位置,返回count(规律:count的就返回count,True/False就返回True/False)
- 递归类似permutation,所以用used记录
-
=m and <=n:
- 类似strobogramatic III,作为recursion的结束条件。
- 为了省事,不pass in当前len,可以减m/n:
- 这里有技巧:如果m<=0,表示至少有一个解(如果之前的,就表示之前的,本位置不选,如果初始,就是空,符合>=0的条件),只有n<=0(不选,但是也要返回累积的),提前结束返回1
- valid条件:used没有用并且:具体来说,
- 一个used变量用bit可以表示9个位置的True/False,used用来记录当前dfs递归的stacktrace
- 技巧:对于下一个位置的测试点i,j:得到used2,如果used2>used:表示i,j没有用
- 无间隔条件:当前点和下一个测试点之间的中点有没有?因为是3X3,2个点之间差0或者1,所以可以用这个条件%2。
- 错误理解:不是横纵都为%2==1,而是any(想想一个方向可以坐标相同)。注意跨越6格斜角是符合的。
- 符合的是%21,不是0
- 初始:注意recursion内loop,开始点选(1,1)是因为所有其他点都符合%2==1条件,而(1,1)这个点第三个条件满足。所以recursion内任意点都可以初始。
https://repl.it/Cmup/1 (backtracking: beat 22.73%)
https://repl.it/Cmup/2 (dp, beat 100%)
- dp: dp[used][j]: all possible used of 9: 1<<9, end with j的个数。递推:
- loop: 最外层是used,所以从less used到more used构建
- 当前目标找到所有used里以某个i结尾,loop on last end with j, 这样可以扩展到下一个,dp[used][j]已经count过。
- dp有很多hole是invalid的。比如used里没有i或者j
- init: 如果只有1个键,那是1个
# 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:
# Given m = 1, n = 1, return 9.
# Hide Company Tags Google
# Hide Tags Dynamic Programming Backtracking
class Solution(object):
def numberOfPatterns(self, m, n):
"""
:type m: int
:type n: int
:rtype: int
"""
def dfs(m, n, used, x, y):
res = m<=0
if n<=0:
return 1
for i in xrange(3):
for j in xrange(3):
I,J,used2 = x+i,y+j,used | (1<<(i*3+j))
# print I,J,bin(used2)
if used2>used and (I%2 or J%2 or used2 & 1<<(I/2*3+J/2)):
res+=dfs(m-1,n-1, used2, i,j)
return res
return dfs(m, n, 0, 1, 1)
sol = Solution()
assert sol.numberOfPatterns(1,1)==9, "must be 9"
class Solution(object):
def numberOfPatterns(self, m, n):
"""
:type m: int
:type n: int
:rtype: int
"""
def setused(used, i):
return used | (1<<i) # error: not &: & is used to get bit 1, not set bit 1
def unsetused(used, i):
return used & ~(1<<i) # error: not | : set to 0
def contains(used, i):
return used & (1<<i) # error: not | : get, not set
def keynumber(used):
count = 0
for i in xrange(9):
count+= (used & 1)
used >>= 1
return count
dp = [[0]*9 for i in xrange(1<<9)]
for i in xrange(9):
dp[setused(0, i)][i] = 1
res = 0
for used in xrange(len(dp)): # error: this is actually number
nk = keynumber(used)
# print bin(used), nk
if nk>n: # error: not >= as currently testing used
continue
for i in xrange(9):
if not contains(used, i):
continue
for j in xrange(9):
if i==j or not contains(used, j): # error: not (contains) as testing used
continue
x0, y0 = i/3, i%3
x1, y1 = j/3, j%3
I,J = x0+x1, y0+y1
if I%2 or J%2 or contains(used, I/2*3+J/2):
# print bin(used), j
dp[used][i]+=dp[unsetused(used, i)][j]
if m<=nk<=n: # error:
# print bin(used), nk, i, dp[used][i]
res+=dp[used][i]
return res
标签:
leetcode
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 用一种新的分类方法梳理设计模式的脉络