LeetCode 851:喧闹和富有
基本思路
这题的基本思路是将富有偏序关系构建成拓扑网络。在构建answer数组时,对每一个person,定位到相应节点在拓扑图中的位置,然后进行DFS搜索,找到quiet最小的<person, value>对,记录答案。
这里要记住将<person, value>对保存在节点中,避免下一次DFS到该节点时进行重复计算,起到一个剪枝的效果。
代码
class Solution {
public:
class node
{
public:
int id;
int minQuiet;
int minPerson;
std::vector<node*> richerVec;
node(int id):id(id), minQuiet(0x7ffffff), minPerson(-1)
{
richerVec = std::vector<node*>();
}
};
std::pair<int, int> findMinQuiet(node* root, vector<int>& quiet)
{
//若该节点已进行过DFS遍历,可直接使用遍历结果
if(root->minPerson != -1)
{
return {root->minPerson, root->minQuiet};
}
int minPerson = root->id;
int minQuiet = quiet[root->id];
//对节点的所有出边节点进行DFS遍历
for(int i=0; i<root->richerVec.size(); i++)
{
pair<int, int> tmp = findMinQuiet(root->richerVec[i],quiet);
if(tmp.second < minQuiet)
{
minQuiet = tmp.second;
minPerson = tmp.first;
}
}
//保存遍历结果
root->minPerson = minPerson;
root->minQuiet = minQuiet;
return {minPerson, minQuiet};
}
vector<int> loudAndRich(vector<vector<int>>& richer, vector<int>& quiet) {
int persons = quiet.size();
//构造拓扑图节点
std::vector<node*> nodeList(persons, nullptr);
for(int i=0; i<persons; i++)
{
nodeList[i] = new node(i);
}
//构造拓扑图
for(int i=0; i<richer.size() ;i++)
{
int poor = richer[i][1];
int rich = richer[i][0];
node* pt = nodeList[rich];
nodeList[poor]->richerVec.push_back(pt);
}
//搜索拓扑网络,构建答案
std::vector<int> answer(persons,-1);
for(int i=0; i<persons; i++)
{
answer[i] = findMinQuiet(nodeList[i],quiet).first;
}
return answer;
}
};