题目来源:🔒LeetCode 351: 安卓系统手势解锁
问题抽象: 给定两个整数 m 和 n(1 ≤ m ≤ n ≤ 9),要求计算在 安卓手势解锁模式 中,所有长度介于 m 到 n 的 有效手势路径数量,满足以下核心需求:
-
手势规则定义:
- 手势路径在
3×3网格(点编号1至9)上绘制,连续连接 未访问过的点; - 相邻点跳跃约束:若两点间存在 未访问的中间点(如
1→3需经过2),则跳跃 无效(除非中间点已被访问)。
- 手势路径在
-
路径有效性要求:
- 路径长度需满足
m ≤ len ≤ n(len为连接的点数); - 每个点 仅可使用一次(路径不可重复访问点);
- 路径 必须连续(相邻两点需满足跳跃规则)。
- 路径长度需满足
-
计算约束:
- 需统计 所有可能的起点(
9个点)生成的合法路径; - 时间复杂度 O(9!)(回溯搜索),空间复杂度 O(9)(存储访问状态);
- 需预处理 跳跃规则映射(如
(1,3)→2,(1,7)→4等)。
- 需统计 所有可能的起点(
-
边界处理:
m=1, n=1时,输出9(仅单点手势);m=1, n=2时,输出65(单点9种 + 两点56种);- 对称性优化:点
1,3,7,9对称,点2,4,6,8对称,点5独立。
输入:整数 m(最小长度),整数 n(最大长度)。
输出:所有有效手势路径的总数量(整数值)。
解题思路
题目要求计算在安卓解锁屏幕中,至少连接 m 个且至多连接 n 个键的所有解锁模式数量。解决思路:
- 预处理跳跃关系:使用二维数组
jump记录任意两点间的中间点(如jump[1][3] = 2)。 - DFS + 回溯:遍历每个起点(1~9),通过DFS生成所有有效路径:
- 维护
visited数组记录已访问点。 - 对于当前点
cur,尝试访问下一个点next:- 若
next未被访问,检查cur到next是否需要中间点:- 不需要中间点(
jump[cur][next] == 0),或中间点已被访问,则允许访问next。
- 不需要中间点(
- 若
- 路径长度在
[m, n]时计数。
- 维护
- 剪枝优化:路径长度达到
n时停止深入(最多连接n个点)。 - 对称性优化:利用对称性减少重复计算(1/3/7/9对称,2/4/6/8对称,5单独处理),但代码中直接遍历所有起点已足够高效。
代码实现(Java版)🔥点击下载源码
class Solution {
private int[][] jump; // 跳跃数组:jump[i][j]表示i到j的中间点
private boolean

1309

被折叠的 条评论
为什么被折叠?



