https://leetcode-cn.com/problems/throne-inheritance/
一个王国里住着国王、他的孩子们、他的孙子们等等。每一个时间点,这个家庭里有人出生也有人死亡。
这个王国有一个明确规定的皇位继承顺序,第一继承人总是国王自己。我们定义递归函数 Successor(x, curOrder) ,给定一个人 x 和当前的继承顺序,该函数返回 x 的下一继承人。
请你实现 ThroneInheritance 类:
ThroneInheritance(string kingName) 初始化一个 ThroneInheritance 类的对象。国王的名字作为构造函数的参数传入。
void birth(string parentName, string childName) 表示 parentName 新拥有了一个名为 childName 的孩子。
void death(string name) 表示名为 name 的人死亡。一个人的死亡不会影响 Successor 函数,也不会影响当前的继承顺序。你可以只将这个人标记为死亡状态。
string[] getInheritanceOrder() 返回 除去 死亡人员的当前继承顺序列表。
示例:
输入:
["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]]
输出:
[null, null, null, null, null, null, null, ["king", "andy", "matthew", "bob", "alex", "asha", "catherine"], null, ["king", "andy", "matthew", "alex", "asha", "catherine"]]
解释:
ThroneInheritance t= new ThroneInheritance("king"); // 继承顺序:king
t.birth("king", "andy"); // 继承顺序:king > andy
t.birth("king", "bob"); // 继承顺序:king > andy > bob
t.birth("king", "catherine"); // 继承顺序:king > andy > bob > catherine
t.birth("andy", "matthew"); // 继承顺序:king > andy > matthew > bob > catherine
t.birth("bob", "alex"); // 继承顺序:king > andy > matthew > bob > alex > catherine
t.birth("bob", "asha"); // 继承顺序:king > andy > matthew > bob > alex > asha > catherine
t.getInheritanceOrder(); // 返回 ["king", "andy", "matthew", "bob", "alex", "asha", "catherine"]
t.death("bob"); // 继承顺序:king > andy > matthew > bob(已经去世)> alex > asha > catherine
t.getInheritanceOrder(); // 返回 ["king", "andy", "matthew", "alex", "asha", "catherine"]
思路:
构建一棵树,根节点为king, king的孩子为其子节点,由于可以有多个子节点,这里选用了Node::vector<Node*>来存储指向各个子节点的指针。
在ThroneInheritance 类的构造函数中实现根节点的生成。
采用二叉树遍历中的前序遍历思想可以完成任务,这里,先访问根节点,然后访问最左边的子节点为根节点的子树,然后左边第二个节点为根节点的子树...
KO 97%的程序员了。
Note:
1)调用birth(string parentName, string childName)函数时,需要从已建立的树中搜索出parentName节点,以下代码实现了两种方式,一种是对树进行广度优先搜索,locateName函数,
由于频繁调用,导致超时了! 另一种方式是采用unordered_map将每个节点的地址存储起来,从而可以根据Name快速定位到节点,大大节省时间,这种使用map存储地址的方式经常用到。
2)这里选用了Node::vector<Node*>来存储指向各个子节点的指针, 经过实验比使用List<Node*>更快更节省内存, 因为list这种数据结果还要额外存储指针吧。
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <unordered_map>
//https://leetcode-cn.com/problems/throne-inheritance/
//体验到了使用map存储节点地址的高效!
using namespace std;
class ThroneInheritance
{
public:
struct Node {
Node(string str="",int v = 0, vector<Node*> vec = vector<Node*>(0))
:name(str),val(v), child(vec)
{
}
int val;
vector<Node*> child;
string name;
};
ThroneInheritance() {
}
ThroneInheritance(string kingName) {
mRoot = new Node(kingName);
mNodeAddrMap[kingName] = mRoot;
}
void birth(string parentName, string childName) {
//Node* pParent = locateName(parentName);
Node* pParent = locateNameWithMap(parentName);
if (pParent) {
Node* p = new Node(childName);
pParent->child.push_back(p);
mNodeAddrMap[childName] = p;//store name's addr in to map.
}
}
void death(string name) {
//Node* p = locateName(name);
Node* p = locateNameWithMap(name);
if(p)
p->val = -1;//dead
}
const vector<string>& getInheritanceOrder() {
mInheVec.clear();
preOrderTravName(mRoot);
return mInheVec;
}
////
Node* mRoot;
vector<string> mInheVec;
unordered_map<string, Node*> mNodeAddrMap;
Node* locateName(string name) {
if (!mRoot) {
return nullptr;
}
queue<Node*> queCache;
queCache.push(mRoot);
while (!queCache.empty())
{
Node* p = queCache.front();
queCache.pop();
if (p->name == name) {
return p;
}
for (const auto& pNode : p->child) {
queCache.push(pNode);
}
}
return nullptr;
}
Node* locateNameWithMap(string name) {
if (mNodeAddrMap.find(name)!= mNodeAddrMap.end()) {
return mNodeAddrMap[name];
}
return nullptr;
}
void preOrderTravName(Node* root) {
if (root) {
//cout << root->val << " ";
if (root->val != -1) {
mInheVec.push_back(root->name);
}
for (auto p : root->child) {
preOrderTravName(p);
}
}
}
void preOrderTrav(Node* root) {
if (root) {
cout << root->val << " ";
for (auto p : root->child) {
preOrderTrav(p);
}
}
}
void Test1() {
Node* root = new Node("0", 0);
root->child.push_back(new Node("1",1));
root->child.push_back(new Node("2", 2));
root->child.push_back(new Node("3", 3));
root->child[0]->child.push_back(new Node("10", 10));
root->child[0]->child.push_back(new Node("11", 11));
mRoot = root;
preOrderTrav(mRoot);
Node* p =locateName("11");
if(p)
cout << "p-name=" << p->name;
}
};
void Test2() {
//Node* root = new Node("0", 0);
//root->child.push_back(new Node("1", 1));
//root->child.push_back(new Node("2", 2));
//root->child.push_back(new Node("3", 3));
//root->child[0]->child.push_back(new Node("10", 10));
//root->child[0]->child.push_back(new Node("11", 11));
//mRoot = root;
//const vector<string>& resVec = getInheritanceOrder();
//for (auto str : resVec)
//{
// cout << str << " - ";
//}
//cout << endl;
ThroneInheritance obj("0");
obj.birth("0", "1");
obj.birth("0", "2");
obj.birth("0", "3");
obj.birth("1", "10");
obj.birth("1", "11");
obj.death("1");
const vector<string>& resVec = obj.getInheritanceOrder();
cout << endl;
for (auto str : resVec) {
cout << str << " - ";
}
cout << endl;
}
int main() {
//ThroneInheritance obj;
//obj.Test1();
Test2();
return 1;
}