LeetCode1320.最小移动距离的双指键盘输入问题
作者:天晴的故事_665 | 来源:互联网 | 2024-12-21 13:22
本文探讨了在定制键盘上使用两根手指输入字符串时,如何计算最小移动总距离的问题。键盘布局为标准的5行6列,每个大写字母对应一个特定坐标。通过动态规划算法,我们能够有效地找到最优解。
### 问题描述 在一个XY平面上,有一个定制的键盘布局,如图所示。每个大写英文字母位于特定的坐标处,例如字母A位于(0,0),字母B位于(0,1),字母P位于(2,3),字母Z位于(4,1)。 给定一个待输入的字符串`word`,你需要计算并返回在仅使用两根手指的情况下,键入该字符串所需的最小移动总距离。坐标(x1,y1)和(x2,y2)之间的曼哈顿距离是|x1 - x2| + |y1 - y2|。 注意:两根手指的起始位置是零代价的,不计入移动总距离。手指可以任意选择从哪个字母开始。 #### 示例 ```cpp 示例 1: 输入: word = "CAKE" 输出: 3 解释: 手指1从C到A的距离为2,手指2从K到E的距离为1,总距离为3。 示例 2: 输入: word = "HAPPY" 输出: 6 解释: 手指1从H到A再到Y的距离为6,手指2从P到P的距离为0。 示例 3: 输入: word = "NEW" 输出: 3 示例 4: 输入: word = "YEAR" 输出: 7 ``` #### 提示 - 2 <= word.length <= 300 - 每个字符都是大写英文字母。 ### 解题思路 我们使用动态规划来解决这个问题。定义`dp[i][c1][c2]`表示输入完第i个字符后,手指1在字符c1,手指2在字符c2时的最小移动距离。其中,0表示还没有输入字符,1-26表示A-Z。 初始化时,我们将第一个字符分配给手指1,并设置初始状态为0。接下来,我们遍历剩余字符,更新状态转移方程以计算最小移动距离。 #### 代码实现 ```cpp class Solution { public: int minimumDistance(string s) { vector> pos(27, vector(2)); int count = 1; for (int i = 0; i <5 && count <27; ++i) for (int j = 0; j <6 && count <27; ++j) pos[count++] = {i, j}; // 字符的坐标 int n = s.size(), mindis = INT_MAX; int dp[301][27][27]; memset(dp, 0x7f, sizeof(dp)); dp[0][s[0] - 'A' + 1][0] = 0; // 输入第一个字符给手指1 for (int i = 1; i int c = s[i] - 'A' + 1; // 当前字符序号 1-26 for (int c1 = 1; c1 <= 26; ++c1) { for (int c2 = 0; c2 <= 26; ++c2) { if (dp[i-1][c1][c2] == 0x7f7f7f7f) continue; // 状态不存在 // 当前字母c由第1个手指输入 dp[i][c][c2] = min(dp[i][c][c2], dp[i-1][c1][c2] + abs(pos[c][0] - pos[c1][0]) + abs(pos[c][1] - pos[c1][1])); // 当前字母c由第2个手指输入 if (c2 == 0) // 第二个手指还没输入 dp[i][c1][c] = min(dp[i][c1][c], dp[i-1][c1][c2]); // 第一次输入没有成本 else dp[i][c1][c] = min(dp[i][c1][c], dp[i-1][c1][c2] + abs(pos[c][0] - pos[c2][0]) + abs(pos[c][1] - pos[c2][1])); } } } for (int c1 = 1; c1 <= 26; ++c1) for (int c2 = 0; c2 <= 26; ++c2) mindis = min(mindis, dp[n-1][c1][c2]); return mindis; } }; ``` ### 性能分析 上述代码的时间复杂度为O(n * 26^2),空间复杂度为O(n * 26^2),其中n是字符串长度。实际运行时间为32ms,内存消耗为7.5MB。 更多内容请关注我的博客和公众号,一起学习进步!
推荐阅读
本文介绍如何使用 Python 将一个字符串按照指定的行和元素分隔符进行两次拆分,最终将字符串转换为矩阵形式。通过两种不同的方法实现这一功能:一种是使用循环与 split() 方法,另一种是利用列表推导式。 ...
[详细]
蜡笔小新 2024-12-28 12:15:45
Java 中 Writer flush()方法,示例 ...
[详细]
蜡笔小新 2024-12-28 06:41:52
本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ...
[详细]
蜡笔小新 2024-12-28 04:11:47
Java 中的 BigDecimal pow()方法,示例 ...
[详细]
蜡笔小新 2024-12-27 20:54:03
本文详细介绍了IBM DB2数据库在大型应用系统中的应用,强调其卓越的可扩展性和多环境支持能力。文章深入分析了DB2在数据利用性、完整性、安全性和恢复性方面的优势,并提供了优化建议以提升其在不同规模应用程序中的表现。 ...
[详细]
蜡笔小新 2024-12-28 13:22:19
本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ...
[详细]
蜡笔小新 2024-12-28 11:30:01
本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ...
[详细]
蜡笔小新 2024-12-28 10:51:55
本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ...
[详细]
蜡笔小新 2024-12-28 10:36:30
本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ...
[详细]
蜡笔小新 2024-12-28 10:30:14
Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ...
[详细]
蜡笔小新 2024-12-28 08:54:34
本文介绍了如何使用 Spring Boot DevTools 实现应用程序在开发过程中自动重启。这一特性显著提高了开发效率,特别是在集成开发环境(IDE)中工作时,能够提供快速的反馈循环。默认情况下,DevTools 会监控类路径上的文件变化,并根据需要触发应用重启。 ...
[详细]
蜡笔小新 2024-12-28 04:42:15
本文探讨了Hive中内部表和外部表的区别及其在HDFS上的路径映射,详细解释了两者的创建、加载及删除操作,并提供了查看表详细信息的方法。通过对比这两种表类型,帮助读者理解如何更好地管理和保护数据。 ...
[详细]
蜡笔小新 2024-12-27 20:21:48
本文探讨了Java中类成员的初始化顺序、静态引入、可变参数以及finalize方法的应用。通过具体的代码示例,详细解释了这些概念及其在实际编程中的使用。 ...
[详细]
蜡笔小新 2024-12-27 19:39:42
本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ...
[详细]
蜡笔小新 2024-12-27 18:51:49
主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ...
[详细]
蜡笔小新 2024-12-27 18:18:10