LC 851. Loud and Rich

In a group of N people (labelled 0, 1, 2, ..., N-1), each person has different amounts of money, and different levels of quietness.

For convenience, we'll call the person with label x, simply "person x".

We'll say that richer[i] = [x, y] if person x definitely has more money than person y.  Note that richer may only be a subset of valid observations.

Also, we'll say quiet[x] = q if person x has quietness q.

Now, return answer, where answer[x] = y if y is the least quiet person (that is, the person y with the smallest value of quiet[y]), among all people who definitely have equal to or more money than person x.

 

Example 1:

Input: richer = [[1,0],[2,1],[3,1],[3,7],[4,3],[5,3],[6,3]], quiet = [3,2,5,4,6,1,7,0]
Output: [5,5,2,5,4,5,6,7]
Explanation: 
answer[0] = 5.
Person 5 has more money than 3, which has more money than 1, which has more money than 0.
The only person who is quieter (has lower quiet[x]) is person 7, but
it isn't clear if they have more money than person 0.

answer[7] = 7.
Among all people that definitely have equal to or more money than person 7
(which could be persons 3, 4, 5, 6, or 7), the person who is the quietest (has lower quiet[x])
is person 7.

The other answers can be filled out with similar reasoning.

Note:

  1. 1 <= quiet.length = N <= 500
  2. 0 <= quiet[i] < N, all quiet[i] are different.
  3. 0 <= richer.length <= N * (N-1) / 2
  4. 0 <= richer[i][j] < N
  5. richer[i][0] != richer[i][1]
  6. richer[i]'s are all different.
  7. The observations in richer are all logically consistent.

 

 

Runtime: 120 ms, faster than 8.56% of C++ online submissions for Loud and Rich.

class Solution {
public:
  vector<int> loudAndRich(vector<vector<int>>& richer, vector<int>& quiet) {
    int n = quiet.size();
    vector<int> ret(n,0);
    for(int i=0; i<n; i++) ret[i] = i;
    vector<unordered_set<int>> graph(quiet.size());
    vector<unordered_set<int>> revgraph(quiet.size());
    for(int i=0; i<richer.size(); i++){
      graph[richer[i][0]].insert(richer[i][1]);
    }
    for(int i=0; i<richer.size(); i++){
      revgraph[richer[i][1]].insert(richer[i][0]);
    }
    queue<int> q;
    for(int i=0; i<n; i++){
      if(revgraph[i].empty()) q.push(i);
    }
    while(!q.empty()){
      int node = q.front(); q.pop();
      for(auto it=graph[node].begin(); it!=graph[node].end(); it++){
        int childnode = *it;
        ret[childnode] = quiet[ret[node]] > quiet[ret[childnode]] ? ret[childnode] : ret[node];
        revgraph[childnode].erase(node);
        if(revgraph[childnode].empty()) q.push(childnode);
      }
    }
    return ret;
  }
};

 

还有一种dfs的做法,速度要快很多,因为没有用到字典删除。而且还有这一句话

 

auto __  = []() {std::ios::sync_with_stdio(false); return 0;}();

 

 

auto __ =[]() { std::ios::sync_with_stdio(false); cin.tie(nullptr); return nullptr; }();
void
dfs(vector<vector<int>> & graph,vector<int> & go,vector<int> & retv,vector<int>quiets,int index) { int quiet = quiets[index]; go[index] = 1; retv[index] = index; for(int i=0;i<graph[index].size();i++) { if(go[graph[index][i]]) { int person = retv[graph[index][i]]; if(quiet>quiets[person]) { quiet = quiets[person]; retv[index] = person; } } else { dfs(graph,go,retv,quiets,graph[index][i]); int person = retv[graph[index][i]]; if(quiet>quiets[person]) { quiet = quiets[person]; retv[index] = person; } } } } class Solution { public: vector<int> loudAndRich(vector<vector<int>>& richer, vector<int>& quiet) { vector<vector<int>> graph(quiet.size(),vector<int>()); if(quiet.size() == 0) return vector<int>(); for(auto ele:richer) { graph[ele[1]].push_back(ele[0]); } vector<int> go(quiet.size(),0); vector<int> retv(quiet.size(),0); for(int i =0;i<quiet.size();i++) { if(go[i]==0) { dfs(graph,go,retv,quiet,i); } } return retv; } };

 

posted @ 2018-12-29 16:14  yuxihong  阅读(191)  评论(0编辑  收藏  举报