1. 程式人生 > 實用技巧 >【LeetCode/LintCode】 題解丨Facebook面試題:序列重構

【LeetCode/LintCode】 題解丨Facebook面試題:序列重構

判斷是否序列 ​org​ 能唯一地由 ​seqs​重構得出. ​org​是一個由從1到n的正整數排列而成的序列,1≤n≤10​^4​​。 重構表示組合成​seqs​的一個最短的父序列 (意思是,一個最短的序列使得所有 ​seqs​裡的序列都是它的子序列).

判斷是否有且僅有一個能從 ​seqs​重構出來的序列,並且這個序列是​org​。

線上評測地址:

LintCode 領釦

樣例1:
輸入:org = [1,2,3], seqs = [[1,2],[1,3]]
輸出: false
解釋:
[1,2,3] 並不是唯一可以被重構出的序列,還可以重構出 [1,3,2]
樣例2:
輸入: org = [1,2,3], seqs = [[1,2]]
輸出: false
解釋:
能重構出的序列只有 [1,2].
樣例3:
輸入: org = [1,2,3], seqs = [[1,2],[1,3],[2,3]]
輸出: true
解釋:
序列 [1,2], [1,3], 和 [2,3] 可以唯一重構出 [1,2,3].
樣例4:
輸入:org = [4,1,5,2,6,3], seqs = [[5,2,6,3],[4,1,5,2]]
輸出:true

【題解】

九章演算法班裡講過的拓撲排序,只要保證 queue 裡最多同時只有一個元素即可。 所以這是 queue 用 list 然後每次 pop 也可以,反正只有一個數。

public class Solution {
    /**
     * @param org: a permutation of the integers from 1 to n
     * @param seqs: a list of sequences
     * @return: true if it can be reconstructed only one or false
     */
    public boolean sequenceReconstruction(int[] org, int[][] seqs) {
        Map<Integer, Set<Integer>> graph = buildGraph(seqs);
        List<Integer> topoOrder = getTopoOrder(graph);
        
        if (topoOrder == null || topoOrder.size() != org.length) {
            return false;
        }
        for (int i = 0; i < org.length; i++) {
            if (org[i] != topoOrder.get(i)) {
                return false;
            }
        }
        return true;
    }
    
    private Map<Integer, Set<Integer>> buildGraph(int[][] seqs) {
        Map<Integer, Set<Integer>> graph = new HashMap();
        for (int[] seq : seqs) {
            for (int i = 0; i < seq.length; i++) {
                if (!graph.containsKey(seq[i])) {
                    graph.put(seq[i], new HashSet<Integer>());
                }
            }
        }
        for (int[] seq : seqs) {
            for (int i = 1; i < seq.length; i++) {
                graph.get(seq[i - 1]).add(seq[i]);
            }
        }
        return graph;
    }
    
    private Map<Integer, Integer> getIndegrees(Map<Integer, Set<Integer>> graph) {
        Map<Integer, Integer> indegrees = new HashMap();
        for (Integer node : graph.keySet()) {
            indegrees.put(node, 0);
        }
        for (Integer node : graph.keySet()) {
            for (Integer neighbor : graph.get(node)) {
                indegrees.put(neighbor, indegrees.get(neighbor) + 1);
            }
        }
        return indegrees;
    }
    
    private List<Integer> getTopoOrder(Map<Integer, Set<Integer>> graph) {
        Map<Integer, Integer> indegrees = getIndegrees(graph);
        Queue<Integer> queue = new LinkedList();
        List<Integer> topoOrder = new ArrayList();
        
        for (Integer node : graph.keySet()) {
            if (indegrees.get(node) == 0) {
                queue.offer(node);
                topoOrder.add(node);
            }
        }
        
        while (!queue.isEmpty()) {
            if (queue.size() > 1) {
                return null;
            }
            
            Integer node = queue.poll();
            for (Integer neighbor : graph.get(node)) {
                indegrees.put(neighbor, indegrees.get(neighbor) - 1);
                if (indegrees.get(neighbor) == 0) {
                    queue.offer(neighbor);
                    topoOrder.add(neighbor);
                }
            }
        }
        
        if (graph.size() == topoOrder.size()) {
            return topoOrder;
        }
        
        return null;
    }
}

更多題解參考:

九章演算法 - 幫助更多中國人找到好工作,矽谷頂尖IT企業工程師實時線上授課為你傳授面試技巧