You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

字母乱序字符串转数字求和的Top-Down DP代码错误排查

问题排查与修复思路

核心问题分析

你的Top-Down DP方案在短字符串正常、长字符串输出0,本质是状态设计、匹配逻辑或递归返回逻辑存在漏洞,导致长字符串的递归路径无法找到有效解,最终返回默认的0值(而非正确累加)。

常见错误点及修复方案

1. 状态设计缺陷:$标记导致状态混淆

用$标记已使用字符再结合排序字符串作为DP状态,容易出现相同剩余字符但$位置不同的重复状态,或者替换$时的字符位置错误,导致缓存的状态结果无效。

修复:
放弃$标记,直接用剩余字符的排序字符串作为DP状态。匹配数字拼写后,直接从原字符串中移除对应字符,将剩余字符重新排序生成新状态。这样状态唯一且准确,避免$带来的歧义。

2. 数字匹配逻辑:逐个替换而非计数校验

如果代码是逐个查找并替换字符(比如找第一个'o'、第一个'n'来匹配"one"),长字符串中可能出现替换错误的字符,导致剩余字符无法组成后续数字,最终递归返回0。

修复:
用字符计数的方式校验匹配:

  • 对当前字符串和目标数字的拼写,分别统计每个字符的出现次数
  • 若数字拼写的所有字符计数都≤当前字符串的计数,说明可以匹配
  • 生成剩余字符串时,将当前字符串的每个字符计数减去数字拼写的对应计数,再将剩余字符拼接排序成新状态

3. 递归返回逻辑:错误返回0而非回溯

如果代码中遇到某个数字匹配失败时直接返回0,而不是跳过该数字尝试其他可能,长字符串中只要有一个分支失败就会直接返回0,忽略了其他有效路径。

修复:

  • 递归终止条件:当剩余字符串为空时,返回0(无剩余字符可组成数字)
  • 遍历所有数字拼写,对每个可匹配的数字,递归计算剩余状态的结果,加上当前数字的值,作为当前状态的候选结果
  • 因为题目明确输入是合法的(所有字符都能组成数字),所以必然存在至少一个有效候选结果,取该结果作为当前状态的缓存值返回

4. 记忆化缓存:错误缓存无效状态

如果缓存中错误地将某个中间状态的结果存为0(比如某次递归失败时的返回值),后续遇到该状态会直接取0,导致整个递归链错误。

修复:

  • 缓存只存储有效结果:只有当递归得到的结果是合法的(比如≥0,因为数字总和非负),才存入缓存
  • 初始时缓存中不存储0值,只有当剩余字符串为空时才返回0

代码修正示例片段

# 数字与对应拼写的映射
num_map = [
    (0, "zero"), (1, "one"), (2, "two"), (3, "three"),
    (4, "four"), (5, "five"), (6, "six"), (7, "seven"),
    (8, "eight"), (9, "nine")
]
cache = {}

def dp(s):
    if not s:
        return 0
    if s in cache:
        return cache[s]
    total = 0
    for num, word in num_map:
        # 统计当前字符串和单词的字符计数
        s_count = {}
        for c in s:
            s_count[c] = s_count.get(c, 0) + 1
        word_count = {}
        for c in word:
            word_count[c] = word_count.get(c, 0) + 1
        # 检查是否可以匹配
        valid = True
        for c in word_count:
            if s_count.get(c, 0) < word_count[c]:
                valid = False
                break
        if valid:
            # 生成剩余字符串
            remaining = []
            for c in s_count:
                remaining.extend([c] * (s_count[c] - word_count.get(c, 0)))
            remaining_s = ''.join(sorted(remaining))
            # 递归计算
            res = num + dp(remaining_s)
            # 题目输入为唯一解,找到即可返回
            total = res
            break
    cache[s] = total
    return total

# 测试长字符串
input_str = "towsnveefourfiveone"
sorted_input = ''.join(sorted(input_str))
print(dp(sorted_input))  # 输出19

关键验证点

  • 运行修正后的代码测试长字符串,确认返回19
  • 检查缓存中的状态是否正确对应剩余字符的总和
  • 确保每个数字匹配时的字符计数逻辑正确,不会出现漏减或多减的情况

内容的提问来源于stack exchange,提问作者htaritoyj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 20:52:49