[Leetcode] 269. Alien Dictionary

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

Solution:
Topological Sort
建立拓扑图并寻找所有字符的入度(buildGraph),再寻找入度为0的字符取出,邻接字符入度减一(bfs)

class Solution {
    public String alienOrder(String[] words) {
        Map<Character, Set<Character>> map = new HashMap<>();
        int[] indegree = new int[26];
        // 利用buildGraph记录邻接字符(map)和所有字符的入度(indegree)
        buildGraph(indegree, map, words);
        // 不断取出入度为1的字符并存到最后的结果中
        return bfs(indegree, map);
        
    }
    
    public void buildGraph(int[] indegree, Map<Character, Set<Character>> map, String[] words) {
    	// words中存在的所有字符
        for(String word : words) {
            for(char ch : word.toCharArray()) {
                map.putIfAbsent(ch, new HashSet<Character>());
            }
        }
        
        // 寻找字符顺序
        for(int i = 1; i < words.length; i++) {
            String first = words[i-1];
            String second = words[i];
            int len = Math.min(first.length(), second.length());
            for(int j = 0; j < len; j++) {
            	// 寻找第一个不同的字符
                if(first.charAt(j) != second.charAt(j)) {
                	// 出度
                    char out = first.charAt(j);
                    // 入度
                    char in = second.charAt(j);
                    // 只有遇见还没有被记录过入度的字符时进行存储和入度记录
                    // 一是因为HashSet存入相同的值会报异常
                    // 二是因为入度只需要记录一次即可
                    if(!map.get(out).contains(in)) {
                        map.get(out).add(in);
                        indegree[in - 'a']++; // 用[in - 'a']可以将字母存入对应index的位置
                    }
                    // 一对单词中,一旦出现一个字符不同,之后字符的顺序都失去意义
                    // 所以直接break
                    break;
                }
            }
        }
    }
    
    public String bfs(int[] indegree, Map<Character, Set<Character>> map) {
        StringBuilder sb = new StringBuilder();
        Queue<Character> q = new LinkedList<>();
        // 只需要存已经在keySet中的字符,不需要遍历所有26个字母
        // 如果入度为0,存入queue
        for(char ch : map.keySet()) {
            if(indegree[ch - 'a'] == 0) {
                q.offer(ch);
            }
        }
        
        
        while(!q.isEmpty()) {
        	// 将入度为0的字符存入结果sb中
            char out = q.poll();
            sb.append(out);
            
            // 拓扑(queue)中已经取出(poll)的node,其邻接node的入度-1
            for(char in : map.get(out)) {
                indegree[in - 'a']--;
                // 寻找入度为0的字母存入queue
                if(indegree[in - 'a'] == 0) {
                    q.offer(in);
                }
            }
        }
        // 检查sb的长度,如果和words中的字母个数相同说明order是valid,否则的话order中要么存在多余的字母,要么就是少字母
        return sb.length() == map.size() ? sb.toString() : "";
    }
}

Reference: https://www.youtube.com/watch?v=RIrTuf4DfPE

Comments: 这题理解到血压升高,还是太垃圾了

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值