LeetCode 269.火星词典

现有一种使用英语字母的外星文语言,这门语言的字母顺序与英语顺序不同。

给定一个字符串列表 words ,作为这门语言的词典,words 中的字符串已经 按这门新语言的字母顺序进行了排序

请你根据该词典还原出此语言中已知的字母顺序,并 按字母递增顺序 排列。若不存在合法字母顺序,返回 "" 。若存在多种可能的合法字母顺序,返回其中 任意一种 顺序即可。

字符串 s 字典顺序小于 字符串 t 有两种情况:

  • 在第一个不同字母处,如果 s 中的字母在这门外星语言的字母顺序中位于 t 中字母之前,那么 s 的字典顺序小于 t
  • 如果前面 min(s.length, t.length) 字母都相同,那么 s.length < t.length 时,s 的字典顺序也小于 t
示例 1:
输入:words = ["wrt","wrf","er","ett","rftt"]
输出:"wertf"

示例 2:
输入:words = ["z","x"]
输出:"zx"

示例 3:
输入:words = ["z","x","z"]
输出:""
解释:不存在合法字母顺序,因此返回 ""
提示:
1 <= words.length <= 100
1 <= words[i].length <= 100
words[i] 仅由小写英文字母组成

这道题可能刚看还理解不了意思,我们用示例1 words = ["wrt","wrf","er","ett","rftt"]来走一遍。

  • 首先,wrtwrf,前两个字符wr相同,而第三个字符"tf不同,且wrtwrf前面,因此t的顺序在f前面
  • 接下来,wrfer,第一个字符we不同,且wrfer前面,因此w的顺序在e前面
  • 然后,erett,第一个字符e相同,而第二个字符rt不相同,因此r的顺序在t之前
  • 最后,"et"rftt,第一个字符er不同,因此e的顺序在r前面
    我们可以综合一下之前的结论,t->fw->er->te->r,因此最终可以得出有且仅有一种顺序,即"wertf"

代码实现如下:

class Solution {
    public String alienOrder(String[] words) {
        boolean[] exist=new boolean[26];
        int[] in=new int[26];
        Set<Integer>[] edge=new HashSet[26];
        int count=0;
        for (int i=0;i<26;i++){
            edge[i]=new HashSet<Integer>();
        }
        for (int j=0;j<words.length;j++){
            String str=words[j];
            for (int k=0;k<str.length();k++){
                if (!exist[str.charAt(k)-'a']){
                    count++;
                    exist[str.charAt(k)-'a']=true;
                }
            }
        }

        for (int m=1;m< words.length;m++){
            String pre=words[m-1];
            String nex=words[m];
            int index=0;
            while (index<pre.length()&&index<nex.length()){
                if (pre.charAt(index)==nex.charAt(index))index++;
                else break;
            }
            if (index<pre.length()&&index<nex.length()){
                if (!edge[pre.charAt(index)-'a'].contains(nex.charAt(index)-'a')){
                    in[nex.charAt(index)-'a']++;
                    edge[pre.charAt(index)-'a'].add(nex.charAt(index)-'a');
                }
            }
            if (index<pre.length()&&index>=nex.length())return "";//特殊判断
        }
        
        Queue<Integer> queue=new LinkedList<>();
        StringBuilder sb=new StringBuilder();
        for (int i=0;i<26;i++){
            if (in[i]==0&&exist[i])queue.offer(i);
        }
        
        while (!queue.isEmpty()){
            int po=queue.poll();
            sb.append((char)(po+'a'));
            for (Integer ind:edge[po]){
                in[ind]--;
                if (in[ind]==0){
                    queue.add(ind);
                }
            }
        }
        return sb.length()==count?sb.toString():"";
    }
}

需要注意的是,测试用例有一个特殊的例子:["abc","ab"],这个示例不符合

如果前面 min(s.length, t.length) 字母都相同,那么 s.length < t.length 时,s 的字典顺序也小于 t

的要求,因此需要特别的判断条件。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值