[LeetCode] 935. Knight Dialer

本文介绍了一种使用动态规划解决骑士拨号器问题的方法,详细解释了如何构建dp数组及递推关系式,提供了完整的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接: https://leetcode.com/problems/knight-dialer/

1. 题目介绍

A chess knight can move as indicated in the chess diagram below:

国际象棋中,一个骑士可以按照下面的方法走:
在这里插入图片描述
This time, we place our chess knight on any numbered key of a phone pad , and the knight makes N-1 hops. Each hop must be from one key to another numbered key.

这次我们把这个骑士放到电话号码键盘上。最初,骑士在号码键盘的任意数字上。接下来他要走 N-1步,每一步必须从一个数字跳到另一个数字
在这里插入图片描述
Each time it lands on a key (including the initial placement of the knight), it presses the number of that key, pressing N digits total.
How many distinct numbers can you dial in this manner?
Since the answer may be large, output the answer modulo 10^9 + 7.

Note:
1 <= N <= 5000

骑士每次落到一个数字上时(包括他最初所在的数字),就会按下那个号码。一共会按出 N 位号码。

给出数字 N ,1 <= N <= 5000 ,代表骑士按出的号码位数。
问:骑士可以按出多少种不同的号码?

由于最后的结果可能会很大,因此答案对 109+ 7 取余。

2. 解题思路

注: 本解题思路参考了 https://leetcode.com/problems/knight-dialer/solution/

这个题我想了很久。动态规划最难的两个地方在于构造 dp 数组和推导递推关系式。而这个递推关系式我一直没有想出来。看了官方的题解后才恍然大悟。在这里我直接采用 LeetCode 题解中的思路吧。

我们可以设定一个函数 f ( start , n ) ,f ( start , n )代表了骑士从数字 start 开始,按下 n 位号码的不同走法的数量,这 n 位号码中的第一位就是数字start。

通过观察,可以发现:
从 0 出发,只能走到{4 , 6 },
从 1 出发,只能走到{6 , 8 },
从 2 出发,只能走到{7 , 9 },
从 3 出发,只能走到{4 , 8 },
从 4 出发,只能走到{3 , 9, 0 },
从 5 出发,哪里都去不了
从 6 出发,只能走到{1 , 7 ,0 },
从 7 出发,只能走到{2 , 6 },
从 8 出发,只能走到{1 , 3 },
从 9 出发,只能走到{2 , 4 }.

因此,可以据此得到 f( start , n )的递推关系式。
比如: f( 1 , n ) = f( 6 , n-1 ) + f( 8, n-1 ).
f( 4 , n ) = f( 3 , n-1 ) + f( 9, n-1 ) + f( 0, n-1 ).

于是,我们可以构造一个二维数组 dp[ ][ ] 用来存放 f( start , n )的值。不用每次用到 f( start , n )的值都去重新计算。
dp[ n ][ start ] 中存放 f( start , n )的值。(注意start 是列,n 是行)
最后的答案就是 f(0, N) + f(1, N) + … + f(9, N) 的和。

实现代码

class Solution {
    public int knightDialer(int N) {
		int [][] dp = new int[N+1][10];
		//对于较大的数,可以用_分隔
		int MOD = 1_000_000_007;
		int [][] moves = {
					{4 , 6 },//0
					{6 , 8 },//1
					{7 , 9 },//2
					{4 , 8 },//3
					{3 , 9, 0 },//4
					{ },//5
					{1 , 7 ,0 },//6
					{2 , 6 },//7
					{1 , 3 },//8
					{2 , 4 },//9
			};
		
		//填充dp[1]这一行中的每个元素都是1
        //意味着当 N = 1 的时候,只有1种走法:停在原地
        //dp[0]这一行是没有用的,因为N不可能为0
        Arrays.fill(dp[1], 1);
       
        for(int i = 2 ; i<=N ; i ++ ) {
        	for(int j = 0 ; j<=9 ; j++) {
        		for(int k = 0 ; k< moves[j].length; k++) {
        			dp[i][j] += dp[i-1][ moves[j][k] ];
        			dp[i][j] %= MOD;
        		}
        	}
        }
        
        long ans = 0;
        for(int i = 0;i<10;i++) {
        	ans += dp[N][i];
        }
        ans %= MOD;
       	return (int)ans;
    }
}

3. 参考资料

https://leetcode.com/problems/knight-dialer/solution/

### 如何在 VSCode 中安装和配置 LeetCode 插件以及 Node.js 运行环境 #### 安装 LeetCode 插件 在 VSCode 的扩展市场中搜索 `leetcode`,找到官方提供的插件并点击 **Install** 按钮进行安装[^1]。如果已经安装过该插件,则无需重复操作。 #### 下载与安装 Node.js 由于 LeetCode 插件依赖于 Node.js 环境,因此需要下载并安装 Node.js。访问官方网站 https://nodejs.org/en/ 并选择适合当前系统的版本(推荐使用 LTS 版本)。按照向导完成安装流程后,需确认 Node.js 是否成功安装到系统环境中[^2]。 可以通过命令行运行以下代码来验证: ```bash node -v npm -v ``` 上述命令应返回对应的 Node.js 和 npm 的版本号。如果没有正常返回版本信息,则可能未正确配置环境变量。 #### 解决环境路径问题 即使完成了 Node.js 的安装,仍可能出现类似 “LeetCode extension needs Node.js installed in environment path” 或者 “command ‘leetcode.toggleLeetCodeCn’ not found” 的错误提示[^3]。这通常是因为 VSCode 未能识别全局的 Node.js 路径或者本地安装的 nvm 默认版本未被正确加载[^4]。 解决方法如下: 1. 手动指定 Node.js 可执行文件的位置 在 VSCode 设置界面中输入关键词 `leetcode`,定位至选项 **Node Path**,将其值设为实际的 Node.js 安装目录下的 `node.exe` 文件位置。例如:`C:\Program Files\nodejs\node.exe`。 2. 使用 NVM 用户管理工具调整默认版本 如果通过 nvm 工具切换了不同的 Node.js 版本,请确保设置了默认使用的版本号。可通过以下指令实现: ```bash nvm alias default <version> ``` 重新启动 VSCode 后测试功能键是否恢复正常工作状态。 --- #### 配置常用刷题语言 最后一步是在 VSCode 设置面板中的 LeetCode 插件部分定义个人习惯采用的主要编程语言作为默认提交方式之一。这样可以减少频繁修改编码风格的时间成本。 --- ### 总结 综上所述,要在 VSCode 上顺利启用 LeetCode 插件及其关联服务,除了基本插件本身外还需额外准备支持性的后台框架——即 Node.js 应用程序引擎;同时针对特定场景下产生的兼容性障碍采取针对性措施加以修正即可达成目标[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值