[算法题]火星词典

题目链接:火星词典

用拓扑排序求解:

1. 用 unordered_map<char, unordered_map<char, bool>> 保存字母的顺序关系,key 表示某个字母,val 表示排在 key 之后的字母的集合,已经记录出现过置为 true

2. 用 unordered_map<char, int> 保存入度,需要初始化,将出现过的字母设置 val 为 0

3. 需要固定一个字符串与其后每个字符串做比较,两个比较的字符串同时从下标 0 开始比较每个字母,不相同时则为 a -> b,b的入度++,更新后 break,循环到遍历结束

4. 定义一个队列,将入度为 0 的字母入队

5. 做一次 bfs

6. 判断是否有环并依此输出相应结果

题解代码:

class Solution 
{
public:
    string alienOrder(vector<string>& words) 
    {
        string res; //保存结果
        unordered_map<char, unordered_map<char, bool>> edges; //保存点与点的连接关系
        unordered_map<char, int> in; //保存入度
        //初始化入度
        for(const auto& s : words)
        {
            for(const auto& c : s)
            {
                if(!in.count(c))
                {
                    in[c] = 0;
                }
            }
        }
        for(int i = 0; i < words.size() - 1; ++i)
        {
            for(int j = i + 1; j < words.size(); ++j)
            {
                for(int k = 0; k < words[i].size(); ++k)
                {
                    //遇到"abc"-"ab"这种对比情况,直接返回""
                    if(k == words[j].size())
                    {
                        return "";
                    }
                    //建立点与点的顺序关系
                    if (words[i][k] != words[j][k])
                    {
                        //如果已经建立过关系则无需重复建立
                        if (!edges[words[i][k]][words[j][k]])
                        {
                            edges[words[i][k]][words[j][k]] = true;
                            in[words[j][k]]++; //更新入度
                        }
                        break;
                    }
                }
            }
        }
        queue<char> q;
        //将入度为0的点添加到队列
        for(const auto& [k, v] : in)
        {
            if(!v)
            {
                q.push(k);
            }
        }
        //bfs
        while(!q.empty())
        {
            char ch = q.front();
            q.pop();
            res += ch;
            for(const auto& [k, _] : edges[ch])
            {
                if(--in[k] == 0)
                {
                    q.push(k);
                }
            }
        }
        //判断是否存在环
        for(const auto& [_, v] : in)
        {
            if(v)
            {
                return "";
            }
        }
        return res;
    }
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值