题目
分析
从题目可以比较简单的看出要使用拓扑排序,显然是需要对item建立图结构的,容易得到item的拓扑排序序列。但是题目要求:同一小组的项目,排序后在列表中彼此相邻!怎么理解这个条件呢?也就是说,属于同一个小组的项目必要可以独立的拎出来,不需要依赖别的小组的进度!假如小组A的部分依赖于小组B,而小组B也有部分依赖于小组A,那么其拓扑排序必定是:B --> A --> B,而无法做到题目要求的同一小组的项目,排序后在列表中彼此相邻。因此为了确定小组间的顺序,我们需要将各个小组要构建图结构,要求其小组结构无环并按拓扑排序输出!然后我们就可以根据小组的拓扑顺序来分别对各个小组内的项目再进行拓扑排序输出!
还有一点很重要的是,因为group = -1的项目不属于任何小组,因此他们不需要满足彼此相邻的条件。但是他们也不能随意的排序,因为存在一些有小组的项目是依赖于没有小组的项目的!因此我们可以对group = -1的item进行group再分配,为他们分配独立的group号!
代码
class Solution {
public:
vector<int> TopSort(vector<vector<int>>& graph, vector<int>& list, vector<int>& indegree){
vector<int> res;
queue<int> q;
for(int i=0;i<list.size();i++){
if(indegree[list[i]] == 0)
q.push(list[i]);
}
while(!q.empty()){
int tmp = q.front();
for(int i=0;i<graph[tmp].size();i++){
indegree[graph[tmp][i]]--;
if(indegree[graph[tmp][i]] == 0 && find(list.begin(),list.end(),graph[tmp][i])!=list.end()) // 这里是为了确保只有属于list的顶点被入队排序
q.push(graph[tmp][i]);
}
q.pop();
res.push_back(tmp);
}
if(res.size() == list.size())
return res;
else{
res.resize(0);
return res;
}
}
vector<int> sortItems(int n, int m, vector<int>& group, vector<vector<int>>& beforeItems) {
// 对于group = -1的item来说为其分配新的group号!关键!
for(int i=0;i<n;i++){
if(group[i] == -1){
group[i] = m;
m++;
}
}
// 对不同group的item进行分类
vector<vector<int>> groupItem(m,vector(0,0));
for(int i=0;i<n;i++){
groupItem[group[i]].push_back(i);
}
vector<vector<int>> itemGraph(n,vector<int>(0,0));
vector<vector<int>> groupGraph(m,vector<int>(0,0));
vector<int> itemIndegree(n,0);
vector<int> groupIndegree(m,0);
// 记录group的图结构以及group的入度
for(int i=0;i<beforeItems.size();i++){
int currentGroup = group[i];
for(int j=0;j<beforeItems[i].size();j++){
int beforeGroup = group[beforeItems[i][j]];
if(beforeGroup!=currentGroup){
groupGraph[beforeGroup].push_back(currentGroup);
groupIndegree[currentGroup]++;
}
// 下面是对于find(list.begin(),list.end(),graph[tmp][i])!=list.end()的优化,但是不太好理解,用于防止不属于某一group的顶点被Top排序
// else{
// itemGraph[beforeItems[i][j]].push_back(i);
// itemIndegree[i]++;
// }
}
}
// 记录item的图结构以及item的入度
for(int i=0;i<beforeItems.size();i++){
for(int j=0;j<beforeItems[i].size();j++){
itemGraph[beforeItems[i][j]].push_back(i);
itemIndegree[i]++;
}
}
// 获取group关系的拓扑排序
vector<int> groupList(m,0);
for(int i=0;i<m;i++)
groupList[i] = i;
vector<int> groupTopSort = TopSort(groupGraph,groupList,groupIndegree);
if(groupTopSort.size() == 0){
return groupTopSort;
}
// 对各个group内的item们进行top排序
vector<int> res;
for(int i=0;i<groupTopSort.size();i++){
vector<int> itemTopSort = TopSort(itemGraph,groupItem[groupTopSort[i]],itemIndegree);
if(itemTopSort.size() == 0 && groupItem[groupTopSort[i]].size()!=0)
return itemTopSort;
else{
for(int m=0;m<itemTopSort.size();m++)
res.push_back(itemTopSort[m]);
}
}
return res;
}
};