LeetCode 423 - 从英文中重建数字


文章目录

摘要

这道题《LeetCode 423. 从英文中重建数字(Reconstruct Original Digits from English)》挺有意思。

它不是那种常规的数值运算题,而更像是一个"单词拼图"挑战。

题目把一些英文数字单词(zero, one, two, ..., nine)打乱顺序混合在一起,我们要根据这些字母重新推算出原始的数字序列。

看起来有点像解谜游戏,其实考的就是"字符串计数 + 特征提取"的能力。

这种题型在自然语言处理、OCR后文本修复、甚至语音识别转写矫正中都有类似的逻辑。

描述

给定一个字符串 s,其中包含被打乱顺序的英文单词表示的数字(zeronine)。

要求我们按升序返回这些数字的字符串表示。

例如:

txt 复制代码
输入: s = "owoztneoer"
输出: "012"
解释: "zero" + "one" + "two" 的字母混合在一起。

再比如:

txt 复制代码
输入: s = "fviefuro"
输出: "45"
解释: 包含 "four" + "five"

题目还保证输入一定能组成合法的数字单词集合,不用考虑无法解析的情况。

题解答案

解决这道题的关键在于:每个数字单词都有独特的字母特征

比如:

  • "z" 只出现在 "zero" 中,所以每出现一个 "z",就一定有一个 "0"。
  • "w" 只出现在 "two" 中。
  • "u" 只出现在 "four" 中。
  • "x" 只出现在 "six" 中。
  • "g" 只出现在 "eight" 中。

这些独特字符让我们可以先识别出部分数字。

然后再根据这些数字中已用掉的字母,反推出剩下的数字。

举个例子:

  • "h" 出现在 "three" 和 "eight" 中,但如果先算出 "eight",剩下的 "h" 只能来自 "three"。
  • "f" 出现在 "four" 和 "five" 中,去掉 "four" 后剩下的 "f" 就属于 "five"。

所以整个过程其实是一个按特征顺序剥洋葱的过程。

题解代码分析

下面是完整可运行的 Swift 代码:

swift 复制代码
import Foundation

class Solution {
    func originalDigits(_ s: String) -> String {
        // 1. 统计每个字母的出现次数
        var count = [Character: Int]()
        for c in s {
            count[c, default: 0] += 1
        }

        // 2. 用数组存每个数字出现的次数
        var res = [Int](repeating: 0, count: 10)

        // 3. 按独特字符特征判断数字
        res[0] = count["z"] ?? 0  // zero
        res[2] = count["w"] ?? 0  // two
        res[4] = count["u"] ?? 0  // four
        res[6] = count["x"] ?? 0  // six
        res[8] = count["g"] ?? 0  // eight

        // 4. 推导剩余数字
        res[3] = (count["h"] ?? 0) - res[8] // three
        res[5] = (count["f"] ?? 0) - res[4] // five
        res[7] = (count["s"] ?? 0) - res[6] // seven
        res[1] = (count["o"] ?? 0) - res[0] - res[2] - res[4] // one
        res[9] = (count["i"] ?? 0) - res[5] - res[6] - res[8] // nine

        // 5. 组合结果
        var ans = ""
        for i in 0..<10 {
            ans += String(repeating: "\(i)", count: res[i])
        }
        return ans
    }
}

// Demo 测试
let s = Solution()
print("测试1:", s.originalDigits("owoztneoer"))  // 输出 "012"
print("测试2:", s.originalDigits("fviefuro"))    // 输出 "45"

代码解析

  1. 计数字母:用一个字典统计每个字母出现的次数。

  2. 识别独特字符

    • "z" 对应 0
    • "w" 对应 2
    • "u" 对应 4
    • "x" 对应 6
    • "g" 对应 8
  3. 再推剩余的

    因为这些数字会"消耗"掉某些字母,所以我们减去它们的数量,再得出其他数字的数量。

  4. 结果拼接:按从小到大的顺序拼接数字字符串。

这段代码的逻辑非常清晰,也贴近实际字符串统计的套路,完全可以迁移到类似文本频率计算的业务场景中。

示例测试及结果

示例 1:

txt 复制代码
输入: s = "owoztneoer"
输出: "012"

解释:包含 "zero", "one", "two",重新排列后输出 012。

示例 2:

txt 复制代码
输入: s = "fviefuro"
输出: "45"

解释:包含 "five", "four",升序排列后输出 45。

执行结果:

txt 复制代码
测试1: 012
测试2: 45

代码输出与预期一致。

时间复杂度

O(N)

每个字符只统计和访问一次,后续推导都是常数操作,因此整体线性时间复杂度。

即使字符串长度达到 10⁵ 级别,也完全没问题。

空间复杂度

O(1)

因为英文字母表大小固定,数字种类也固定,所以空间使用不随输入增长。

严格来说我们用了一些字典和固定数组,但总体为常数级。

总结

这道题的核心是"找到独特特征字符"这一思路,非常有启发性。

它看似是纯算法题,其实背后逻辑和自然语言特征提取符号消歧模式识别等领域非常接近。

在实际开发中,如果遇到:

  • OCR 识别出的混乱文本;
  • 用户输入中带有模糊词;
  • 或日志关键词识别中多个重叠的特征词;

都可以借鉴类似的"频率减法"思路:

先确定独特特征,再逐步剥离剩余部分,最终恢复完整结构。

Swift 在处理这类计数逻辑时的写法也非常简洁------利用字典的默认值和 String(repeating:count:) 拼接方式,整个流程直观又易读。

相关推荐
wfeqhfxz258878218 小时前
YOLO13-C3k2-GhostDynamicConv烟雾检测算法实现与优化
人工智能·算法·计算机视觉
芝士爱知识a18 小时前
2026年AI面试软件推荐
人工智能·面试·职场和发展·大模型·ai教育·考公·智蛙面试
Aaron158818 小时前
基于RFSOC的数字射频存储技术应用分析
c语言·人工智能·驱动开发·算法·fpga开发·硬件工程·信号处理
石去皿19 小时前
大模型面试通关指南:28道高频考题深度解析与实战要点
人工智能·python·面试·职场和发展
程序员辣条19 小时前
AI产品经理:2024年职场发展的新机遇
人工智能·学习·职场和发展·产品经理·大模型学习·大模型入门·大模型教程
AI大模型测试19 小时前
大龄程序员想转行到AI大模型,好转吗?
人工智能·深度学习·机器学习·ai·语言模型·职场和发展·大模型
美团程序员19 小时前
80道经典常见测试面试题
软件测试·面试·职场和发展·软件测试面试
sunguang201819 小时前
“懂不懂管理,一看便知”:做管理就是3件事,抓大、放小、管细做管理,其实就是要做好三件事:抓大、放小、管细。
经验分享·职场和发展
ProcessOn官方账号19 小时前
程序员如何与同龄人拉开差距?这5张让你快速提升认知,打开格局!
深度学习·职场和发展·学习方法
阿福赚美刀19 小时前
跨境电商公司如何高效培养新人:实战经验分享
职场和发展·电脑