双手指打字最短路径问题的图分割解法瓶颈及求解建议
可行解决方案:动态规划优化
针对1e5长度的字符串,必须采用线性/近线性时间复杂度的算法,动态规划结合状态压缩是最优选择,以下是具体思路:
核心逻辑
问题的关键在于,每一步的最优决策仅依赖上一步两根手指的位置,因此可以通过压缩状态空间避免冗余计算:
- 定义两个一维数组:
prev_left[x]:打完前i-1个字符后,左手在第i-1个字符位置、右手在字母x位置的最短总距离prev_right[x]:打完前i-1个字符后,右手在第i-1个字符位置、左手在字母x位置的最短总距离
这种设计将状态数从O(n2626)压缩到O(n*26),对1e5长度的字符串来说完全可控。
状态转移规则
假设当前要输入的字符是curr_c,上一个输入的字符是prev_c:
- 更新
curr_left[x](当前左手在curr_c,右手在x):- 情况1:上一步左手在
prev_c,直接移动到curr_c,总距离 =prev_left[x] + 曼哈顿距离(prev_c, curr_c) - 情况2:上一步右手在
prev_c,左手从x移动到curr_c,总距离 =prev_right[x] + 曼哈顿距离(x, curr_c) - 取两种情况的最小值作为
curr_left[x]的值
- 情况1:上一步左手在
- 更新
curr_right[x](当前右手在curr_c,左手在x):- 情况1:上一步右手在
prev_c,直接移动到curr_c,总距离 =prev_right[x] + 曼哈顿距离(prev_c, curr_c) - 情况2:上一步左手在
prev_c,右手从x移动到curr_c,总距离 =prev_left[x] + 曼哈顿距离(x, curr_c) - 取两种情况的最小值作为
curr_right[x]的值
- 情况1:上一步右手在
初始状态与预准备
- 预计算曼哈顿距离:
先给每个字母分配坐标(按qwerty键盘布局):- 第一行
qwertyuiop:q(0,0)、w(0,1)...p(0,9) - 第二行
asdfghjkl:a(1,0)、s(1,1)...l(1,8) - 第三行
zxcvbnm:z(2,0)、x(2,1)...m(2,6)
提前计算所有字母对的曼哈顿距离,存入26x26的数组,后续直接查询。
- 第一行
- 初始状态设置:
第一个字符c0可由任意手指打出,因此:prev_left[x] = 0(左手在c0,右手在任意x,初始无移动距离)prev_right[x] = 0(右手在c0,左手在任意x,初始无移动距离)
空间优化
由于计算当前状态仅需上一步的状态,无需保存整个历史数组,只需维护prev_left、prev_right两个长度为26的数组即可,空间复杂度降至O(26)。
最终结果计算
遍历完所有字符后,最短路径为min( min(curr_left), min(curr_right) ),即所有可能的手指最终位置中的最小总距离。
复杂度分析
- 时间复杂度:O(n*26),n为字符串长度,总计算量约2.6e6,完全符合时间要求
- 空间复杂度:O(26),仅需固定大小的数组存储状态
补充说明
- 贪心算法失效的原因:仅考虑当前局部最优,会忽略后续字符的位置需求,导致全局总距离增加
- 图划分方法不可行的原因:1e5量级节点会带来O(n²)的复杂度,完全超出计算能力范围,而动态规划通过状态压缩将复杂度降至线性级别
内容的提问来源于stack exchange,提问作者DaniaRepublic
相关产品推荐
相关产品推荐

