【力扣】423.从英文中重建数字

简介: 423. 从英文中重建数字 | 2022-12-15我想先统计每个字母出现次数,然后遍历需重建的单词,单词需要什么字母作为原材料,就直接取什么。于是下面代码的复杂性基于这样一个问题:

423. 从英文中重建数字 | 2022-12-15

我想先统计每个字母出现次数,然后遍历需重建的单词,单词需要什么字母作为原材料,就直接取什么。于是下面代码的复杂性基于这样一个问题:

如果我们打算先重建单词one,建到建不出来为止。但它的字母o在单词two中存在,字母n在单词seven中存在,字母e在单词three中出现。那么重建单词one时是否可能在超支其它单词的字母?


如果我们输入字符串" o n e t w o s e v e n t h r e e " "onetwoseventhree""onetwoseventhree" ,则可能首先重建了两个单词one,然后剩下一堆无法使用的字母。或者说,


是否重建单词本身也可能会有多个正确结果?


接着我对这些单词和它们所包含的字母的分布进行了简单的统计。


e g f i h o n s r u t w v x z
1 1 1
2 2 2
3 3 3 3
4 4 4 4
5 5 5 5
6 6 6
7 7 7 7
8 8 8 8
9 9 9
0 0 0 0

我发现重建单词可以分为三个批次,分别是{two, four, six, eight, zero},{one, three, five, seven}, {nine},如果按照这样的批次顺序去重建单词,上述两个问题就消失了,而同批次的单词之间重建顺序可以是任意的。理由如下:


第一批次中的单词都至少有一个字母是它在这10个单词中独有的,如果这独有的字母还没用完,那必然是还要继续重建那独自占有它的单词。在第一批次结束后,第二批次的单词也都至少有一个字母是它在剩下的6个单词中独有的······


也有其它合适的重建顺序,因为每一次选择重建的单词都可以可能影响后面的选择,而我是在一次选择了一批单词后才进行下一次选择。


如果我们按照三批次的顺序去重建,那么重建结果的排序又成了一个问题,因为我们被要求最后将它们从小到大排序。当然我们可以在重建时先不管顺序,只在最后进行一次排序,但我认为直接进行有序地重建会更快。有序重建只需每次在长度为10的vector<string>中进行查找,而最后排序O ( n ∗ l o g ( n ) )  )是对于  1<=n<=10^5

而言的,桶排序才是最快的,不是吗?

很遗憾我最后的运行时间仅击败了14.98%,那么差距在哪里呢?

//36ms,击败14.98%
class Solution {
public:
    string originalDigits(string s) {
        unordered_map<char, int> hash;
        string char_list = {'e', 'g', 'f', 'i', 'h', 'o', 'n', 's', 'r', 'u', 't', 'w', 
            'v', 'x', 'z'};
        vector<string> word_list = {"two", "four", "six", "eight", "zero", "one",
            "three", "five", "seven", "nine"};
        vector<string> word_list_sort = {"zero", "one", "two", "three", "four", "five",
            "six", "seven", "eight", "nine"};
        vector<char> num_list = {'2', '4', '6', '8', '0', '1', '3', '5', '7', '9'};
        //字母频率统计
        for(auto c : char_list){
            hash[c] = 0;
        }
        for(auto c : s){
            hash[c]++;
        }
        //统计每个单词的重建次数
        unordered_map<string, int> word_list_count;
        for(auto num : word_list){
            bool flag = true;
            while(flag){
                for(auto c : num){  //这里可能可以优化
                    if(hash[c] <= 0){
                        flag = false;
                    }
                }
                if(flag == false){
                    break;
                }
                for(auto c : num){
                    hash[c]--;
                }
                word_list_count[num]++;
            }
        }
        //生成数字字符串
        string r;
        for(auto num : word_list_sort){
            int it = find(word_list.begin(), word_list.end(), num) - word_list.begin();
            int count = word_list_count[num];
            for(int i = 0; i < count; i++){
                r += num_list[it];
            }
        }
        return r;
    }
};

相关文章
|
6月前
|
Go
golang力扣leetcode 406.根据身高重建队列
golang力扣leetcode 406.根据身高重建队列
70 0
|
6月前
代码随想录Day29 贪心04 LeetCode T860 柠檬水找零 T406 根据身高重建队列 T452 用最少得箭引爆气球
代码随想录Day29 贪心04 LeetCode T860 柠檬水找零 T406 根据身高重建队列 T452 用最少得箭引爆气球
41 0
|
12月前
|
算法 Java
代码随想录算法训练营第三十四天 | LeetCode 860. 柠檬水找零、406. 根据身高重建队列、452. 用最少数量的箭引爆气球
代码随想录算法训练营第三十四天 | LeetCode 860. 柠檬水找零、406. 根据身高重建队列、452. 用最少数量的箭引爆气球
63 0
leetcode 406 根据身高重建列队
leetcode 406 根据身高重建列队
58 0
leetcode 406 根据身高重建列队
LeetCode 406. 根据身高重建队列
假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。
82 0
代码随想录刷题|LeetCode 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球
代码随想录刷题|LeetCode 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球
代码随想录刷题|LeetCode 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球
LeetCode:406. 根据身高重建队列
LeetCode:406. 根据身高重建队列
84 0
LeetCode:406. 根据身高重建队列
|
算法
LeetCode 406. 根据身高重建队列
LeetCode 406. 根据身高重建队列
39 0