Throne Inheritance

A kingdom consists of a king, his children, his grandchildren, and so on. Every once in a while, someone in the family dies or a child is born.

The kingdom has a well-defined order of inheritance that consists of the king as the first member. Let's define the recursive function Successor(x, curOrder), which given a person x and the inheritance order so far, returns who should be the next person after x in the order of inheritance.

Successor(x, curOrder):
    if x has no children or all of x's children are in curOrder:
        if x is the king return null
        else return Successor(x's parent, curOrder)
    else return x's oldest child who's not in curOrder

For example, assume we have a kingdom that consists of the king, his children Alice and Bob (Alice is older than Bob), and finally Alice's son Jack.

  1. In the beginning, curOrder will be ["king"].
  2. Calling Successor(king, curOrder) will return Alice, so we append to curOrder to get ["king", "Alice"].
  3. Calling Successor(Alice, curOrder) will return Jack, so we append to curOrder to get ["king", "Alice", "Jack"].
  4. Calling Successor(Jack, curOrder) will return Bob, so we append to curOrder to get ["king", "Alice", "Jack", "Bob"].
  5. Calling Successor(Bob, curOrder) will return null. Thus the order of inheritance will be ["king", "Alice", "Jack", "Bob"].
Using the above function, we can always obtain a unique order of inheritance.

Implement the ThroneInheritance class:

 

Example 1:

Input
["ThroneInheritance", "birth", "birth", "birth", "birth", "birth", "birth", "getInheritanceOrder", "death", "getInheritanceOrder"]
[["king"], ["king", "andy"], ["king", "bob"], ["king", "catherine"], ["andy", "matthew"], ["bob", "alex"], ["bob", "asha"], [null], ["bob"], [null]]
Output
[null, null, null, null, null, null, null, ["king", "andy", "matthew", "bob", "alex", "asha", "catherine"], null, ["king", "andy", "matthew", "alex", "asha", "catherine"]]

Explanation
ThroneInheritance t= new ThroneInheritance("king"); // order: king
t.birth("king", "andy"); // order: king > andy
t.birth("king", "bob"); // order: king > andy > bob
t.birth("king", "catherine"); // order: king > andy > bob > catherine
t.birth("andy", "matthew"); // order: king > andy > matthew > bob > catherine
t.birth("bob", "alex"); // order: king > andy > matthew > bob > alex > catherine
t.birth("bob", "asha"); // order: king > andy > matthew > bob > alex > asha > catherine
t.getInheritanceOrder(); // return ["king", "andy", "matthew", "bob", "alex", "asha", "catherine"]
t.death("bob"); // order: king > andy > matthew > bob > alex > asha > catherine
t.getInheritanceOrder(); // return ["king", "andy", "matthew", "alex", "asha", "catherine"]

 

Constraints:


Solution:

class ThroneInheritance {
    static class Person implements Comparable<Person>{
        String name;
        boolean dead;
        Person parent;
        int birthday;
        
        public Person(String name, int birthday, Person parent) {
            this.name = name;
            this.birthday = birthday;
            this.parent = parent;
            dead = false;
        }
        
        public int compareTo(Person other) {
            return Integer.compare(this.birthday, other.birthday);
        }
        
        @Override
        public boolean equals(Object o) {
            Person other = (Person) o;
            return this.name.equals(other.name);
        }
        
        @Override
        public String toString() {
            return name;
        }
    }
    
    Map<Person, LinkedList<Person>> rel;
    Map<String, Person> map;
    Person king;
    int time;    

    public ThroneInheritance(String kingName) {
        this.rel = new HashMap();
        this.map = new HashMap();
        time = 0;
        king = new Person(kingName, time, null);
        map.put(kingName, king);
        rel.put(king, new LinkedList());
    }
    
    public void birth(String parentName, String childName) {
        Person parent = map.get(parentName);
        rel.putIfAbsent(parent, new LinkedList());
        LinkedList<Person> children = rel.get(parent);
        Person child = new Person(childName, ++time, parent);
        map.put(childName, child);
        children.add(child);
    }
    
    public void death(String name) {
        map.get(name).dead = true;
    }
    
    public List<String> getInheritanceOrder() {
        /*
        Successor(x, curOrder):
            if x has no children or all of x's children are in curOrder:
                if x is the king return null
                else return Successor(x's parent, curOrder)
            else return x's oldest child who's not in curOrder
        */
        List<Person> curOrder = new ArrayList();
        Set<Person> set = new HashSet();
        Person next = king;
        while (next != null) {
            curOrder.add(next);
            set.add(next);
            next = successor(next, set);
        }
        List<String> result = new ArrayList();
        for (Person s : curOrder) {
            if (!s.dead) {
                result.add(s.name);
            }
        }
        return result;
    }
    
    private Person successor(Person curr, Set<Person> set) {
        if (rel.get(curr) == null || set.containsAll(rel.get(curr))) {
            if (curr == king) return null;
            else return successor(curr.parent, set);
        } else {
            for (Person child : rel.get(curr)) {
                if (!set.contains(child)) {
                    return child;
                }
            }
        }
        return null;
    }
}

/**
 * Your ThroneInheritance object will be instantiated and called as such:
 * ThroneInheritance obj = new ThroneInheritance(kingName);
 * obj.birth(parentName,childName);
 * obj.death(name);
 * List<String> param_3 = obj.getInheritanceOrder();
 */