牛客网: 火星文字典

牛客网: 火星文字典

题目描述:

已知一种新的火星文的单词由英文字母(仅小写字母)组成,但是此火星文中的字母先后顺序未知。给出一组非空的火星文单词,且此组单词已经按火星文字典序进行好了排序(从小到大),请推断出此火星文中的字母先后顺序。
输入描述:

一行文本,为一组按火星文字典序排序好的单词(单词两端无引号),单词之间通过空格隔开

输出描述:

按火星文字母顺序输出出现过的字母,字母之间无其他字符,如果无法确定顺序或者无合理的字母排序可能,请输出"invalid"(无需引号)

示例1

输入
z x
输出
zx

示例2

输入
wrt wrf er ett rftt
输出
wertf

示例3

输入
z x z
输出
invalid

解法一

这个题目其实就是一道拓扑排序的题目. 解决思路如下:
用两个 Hash 表, 一个来存每个出现过的字符的入度, 另一个来存一个字符指向的字符集合, 即一个字符应该在另外字符的前面. 然后每次查找入度为零的字符, 并且将这个字符所指向的所有字符的入度减一, 如果有多个入度为零的字符则说明不止一种排序, 输出 "invalid", 如果没有入度为零的字符了, 则说明不能排序, 输出 "invalid". 代码如下:

#include <iostream>
#include <unordered_map>
#include <set>
#include <vector>
#include <cmath>
using namespace std;

string getOrder(vector<string> words){
    unordered_map<char, int> inDegree;
    unordered_map<char, multiset<char> > hashTable;
    for (auto word:words) {
        for (char c:word) {
            inDegree[c] = 0;
            hashTable[c] = multiset<char>();
        }
    }
    for(int i = 1; i < words.size(); ++i) {
        int j = 0, l1 = words[i].length(), l2 = words[i - 1].length();
        while (j < min(l1, l2) && words[i][j] == words[i-1][j]) {
            j ++;
        }
        if (j == min(l1, l2)) continue;
        // c1 排在 c2 前面
        // 因为相同的两个字符可能出现多次, 每次出现都贡献了一个入度
        // 所以要用 multiset 存指向的字符集
        char c1 = words[i-1][j], c2 = words[i][j];
        inDegree[c2] ++;
        hashTable[c1].insert(c2);
    }

    string ans = "";
    for (int i = 0; i < inDegree.size(); ++i) {
        int count = 0;
        char c;
        for (auto p:inDegree) {
            if (p.second == 0) {
                count ++;
                c = p.first;
            }
        }
        if (count == 1) {
            ans += c;
            inDegree[c] --;
            for (char temp:hashTable[c]) {
                inDegree[temp] --;
            }
        } else {
            ans = "invalid";
            break;
        }
    }
    return ans;
}

int main() {
    vector<string> v;
    string s;
    while(cin >> s && getchar() != '\n') {
        v.push_back(s);
    }
    v.push_back(s);
    cout << getOrder(v) << "\n";
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容