算法练习每日一题:从英文中重建数字

423. 从英文中重建数字

给定一个非空字符串,其中包含字母顺序打乱的英文单词表示的数字0-9。按升序输出原始的数字。

注意:

输入只包含小写英文字母。

输入保证合法并可以转换为原始的数字,这意味着像 “abc” 或 “zerone” 的输入是不允许的。

输入字符串的长度小于 50,000。

  • 示例 1:

输入: “owoztneoer”

输出: “012” (zeroonetwo)

  • 示例 2:

输入: “fviefuro”

输出: “45” (fourfive)

链接:https://leetcode-cn.com/problems/reconstruct-original-digits-from-english

题解分析:

  1. 首先枚举 1 ~ 9 的英文单词[“one”, “two”, “three”, “four”, “five”, “six”, “seven”, “eight”, “nine”] 寻找其中的特征
  2. 然后找出单词出现的次数,由大到小排列输出出现的数字,这里的复杂主要是单词识别的问题,完全识别单词比较复杂
  • 有些字母在单词中是重复的,贪心思想寻找单词比较复杂,耐心的寻找单词中一些特征

    “z” 只在 “zero” 中出现

    “w” 只在 “two” 中出现

    “u” 只在 “four” 中出现

    “x” 只在 “six” 中出现

    “g” 只在 “eight” 中出现

    • 这时候通过识别这一个字母,就代表这个单词出现了:

      0 = “z”

      2 = “w”

      4 = “u”

      6 = “x”

      8 = “8”

    • 另外:

      “h” 只在 “three” 和 “eight” 中出现

      “f” 只在 “five” 和 “four” 中出现

      “s” 只在 “seven” 和 “six” 中出现

      “i” 在 “nine”,“five”,“six” 和 “eight” 中出现

      “n” 在 “one”,“seven” 和 “nine” 中出现

    • 那么 3 出现的次数 = "h"的次数 - 8(“g”)的次数;一次类推:

      5 = “f” - “u”

      7 = “s” - “x”

      9 = “i” - “five”-“six” - “eight” = “i” - (“f” - “u”) - “x” - “g”

      1 = “n” - (“i” - (“f” - “u”) - “x” - “g”)*2 - ( “s” - “x”) # nine 中 “n” 有 2 次

如此,只要我们计算出字符串中每个字符出现的数字,就能枚举出 0 ~ 9 出现的次数;Python3 内置的 collections.Counter(s) 能方便的帮我们统计可迭代列表(字符串)中每个元素出现的次数,返回 dict 对象;相应的我们也以 0 ~ 9 为键,存储出现的次数,最后使用 sorted 方法以 key 排序输出。

请参考官方题解,一开始我一直纠结如何完整的识别出单词,以及题干给出的 “输入保证合法并可以转换为原始的数字,这意味着像 “abc” 或 “zerone” 的输入是不允许的。”的用意。

一般在理解题意之后就在考虑如何用代码模拟数学计算解题;这其中有一些典型的方法和思想:枚举,递归,归并排序,随机数快速排序,二分查找,分治法(贪心,动态规划),还有一些复杂数据结构如二叉树,图,集合的特殊算法。题干的理解一般都是数学的枚举、归纳推理过程。

class Solution:
    def originalDigits(self, s):
        strCount = collections.Counter(s)
        rst = collections.defaultdict(int)
        rst[0] = strCount["z"]
        rst[2] = strCount["w"]
        rst[4] = strCount["u"]
        rst[6] = strCount["x"]
        rst[8] = strCount["g"]
        rst[3] = strCount["h"] - rst[8]
        rst[5] = strCount["f"] - rst[4]
        rst[7] = strCount["s"] - rst[6]
        rst[9] = strCount["i"] - rst[5] - rst[6] - rst[8]
        # rst[1] = strCount["n"] - (strCount["i"] - (strCount["f"] - strCount["u"]) - strCount["x"] - strCount["g"]) - (strCount["s"] - strCount["x"])
        rst[1] =  strCount["n"] - rst[9] * 2 - rst[7] # 9 nine , "n" 出现 2 次
        
        # 之后排序后输出,这里用到了 Python 列表的特性 “a” * 3  = “aaa”
        rst = [str(key)*rst[key] for key in sorted(rst.keys())]
        return "".join(rst)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章