Alien Order

https://leetcode.com/problems/alien-dictionary/


单词按照一定次序排序,推导出原始顺序,典型的toposort,非常好的题目和重要的算法。


还是习惯炒肉说的基于indegree的bfs,学神的dfs总觉得别扭。当年老师教的静态链表太差了,太麻烦


有一个point就是里面不出现的单词不能出现,因此一定要mark,不然到时候都丢到queue里面取,因此可以用负数标记-1,因为度都是非负数,


然后图要去除环和重边,考虑到这点用hashmap edge[26]来存比较好


我写了两种写法,再生成图的时候,一种是从比较上下两个单词的第一次不同的单词来生成图,第二种是一个个枚举,然后每次还要取一个前缀串,似乎这个会多一个取串的系数,

第一种写法,还是这种好一些

class Solution {
public:
    string alienOrder(vector<string>& dict) {
        unordered_set<int> edge[26];
        int deg[26];
        memset(deg, -1 ,sizeof deg);
        int maxlen=0;
        for(auto s: dict){
          maxlen=max((int)s.size(), maxlen);
          for(auto se: s){
            deg[se-'a']=0;
          }
        }
        int cnt=0;//get chars count from input
        for(int i=0;i<26;i++){
          if(!deg[i]) cnt++;
        }
        for(int i=1;i<dict.size();i++){
          for(int j=0; j < min(dict[i-1].size(), dict[i].size()); j++){
            char from=dict[i-1][j], to=dict[i][j];
            if(from != to){
              if( !edge[from-'a'].count(to-'a')){
                edge[from-'a'].insert(to-'a');
                deg[to-'a']++;
                break;
              }
            }
          }
        }
        queue<int> q;
        for(int i=0;i<26;i++){
          if(!deg[i]) q.push(i);
        }
        string ans;
        while(!q.empty()){
          auto cur=q.front();q.pop();
          ans.push_back(cur+'a');
          for(auto e: edge[cur]){
            if((--deg[e])==0) q.push(e);
          }
        }
        return ans.size()==cnt ? ans : "";
    }
} S;

第二种写法,只是生成图的部分差别较大

class Solution {
public:
  string alienOrder(vector<string>& words) {
    unordered_set<char> umch;
    int maxlen=0;
    for(auto se: words){
      maxlen=max(maxlen, (int)se.size());
      for(auto e: se){
        umch.insert(e);
      }
    }

    //mark in words and outof words char, as indegree 0 would be put in queue
    int indeg[26];
    memset(indeg, -1, sizeof indeg);
    for(auto e: umch){
      indeg[e-'a']=0;
    }

    int wordnum=words.size();
    unordered_set<int> edge[26];

    for(int i=0;i<maxlen;i++){
      for(int j=0;j<wordnum;j++){
        if(j-1>=0 && i<words[j].size() && i<words[j-1].size() && words[j][i] != words[j-1][i]
           && words[j-1].substr(0, i) == words[j].substr(0, i)){
          int fromindex=words[j-1][i]-'a', toindex=words[j][i]-'a';
          if( !edge[fromindex].count(toindex)){
            edge[fromindex].insert(toindex);
            indeg[toindex]++;
          }
        }
      }
    }
    queue<int> q;
    for(int i=0;i<26;i++){
      if(!indeg[i]) q.push(i);
    }
    string ans;
    while(!q.empty()){
      auto cur=q.front();q.pop();
      ans+=char('a'+cur);
      for(auto e: edge[cur]){
        if(!(--indeg[e])) q.push(e);
      }
    }
    return ans.size() == umch.size() ? ans: "";
  }
} S;


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值