公司共有 n 个项目和 m 个小组,每个项目要不没有归属,要不就由其中的一个小组负责。
我们用 group[i] 代表第 i 个项目所属的小组,如果这个项目目前无人接手,那么 group[i] 就等于
-1。(项目和小组都是从零开始编号的)请你帮忙按要求安排这些项目的进度,并返回排序后的项目列表:
同一小组的项目,排序后在列表中彼此相邻。 项目之间存在一定的依赖关系,我们用一个列表 beforeItems 来表示,其中
beforeItems[i] 表示在进行第 i 个项目前(位于第 i 个项目左侧)应该完成的所有项目。 结果要求:如果存在多个解决方案,只需要返回其中任意一个即可。
如果没有合适的解决方案,就请返回一个 空列表。
示例 1:
输入:n = 8, m = 2,
group = [-1,-1,1,0,0,1,0,-1],
beforeItems = [[],[6],[5],[6],[3,6],[],[],[]]输出:[6,3,4,1,5,2,0,7]
示例 2:
输入:n = 8, m = 2,
group = [-1,-1,1,0,0,1,0,-1],
beforeItems = [[],[6],[5],[6],[3],[],[4],[]]输出:[]
解释:与示例 1 大致相同,但是在排序后的列表中,4 必须放在 6 的前面。
提示:
1 <= m <= n <= 3*10^4
group.length == beforeItems.length == n
-1 <= group[i] <= m-1
0 <= beforeItems[i].length <= n-1
0 <= beforeItems[i][j] <= n-1
i != beforeItems[i][j]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-items-by-groups-respecting-dependencies
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
两遍拓扑排序 先对组内进行排序 然后对所有分组进行排序
对于没有组的其实可以当成单独一个在一组,在最开始给所有没有组的分配上组就好
拓扑排序就dfs就好
class Solution {
List<LinkedList<Integer>> groupAns;
List<HashSet<Integer>> groupEdges;
int[] group;
List<List<Integer>> beforeItems;
int[] color;
List<Integer> groupSort;
int m;
boolean dfs(int i) {
if(color[i] == 2) {
//黑色直接返回就好
return false;
}
if(color[i] == 1) {
return true;//说明存在环
}
color[i] = 1;
for(int to : beforeItems.get(i)) {
if(group[i] != group[to]) {
//记录到组的边里 暂时不管
groupEdges.get(group[i]).add(group[to]);
} else {
if(dfs(to)) {
return true;
}
}
}
groupAns.get(group[i]).add(i);
color[i] = 2;
return false;
}
boolean dfsGroup(int i) {
if(color[i] == 2) {
//黑色直接返回就好
return false;
}
if(color[i] == 1) {
return true;//说明存在环
}
color[i] = 1;
for(int to : groupEdges.get(i)) {
if(dfsGroup(to)) {
return true;
}
}
groupSort.add(i);
color[i] = 2;
return false;
}
public int[] sortItems(int n, int m, int[] group, List<List<Integer>> beforeItems) {
//每个组内部排序
this.group = group;
this.beforeItems = beforeItems;
groupAns = new ArrayList<>();//每个组内的拓扑排序
groupEdges = new ArrayList<>();//每个组的出边
groupSort = new ArrayList<>();//组的排序
color = new int[n];
//没组的编上组
for(int i = 0; i < n; ++i) {
if(group[i] == -1) {
group[i] = m;
++m;
}
}
for(int i = 0; i < m; ++i) {
groupAns.add(new LinkedList<>());
groupEdges.add(new HashSet<>());
}
//第一遍遍历 把组间的边记录上 组内进行dfs
for(int i = 0; i < n; ++i) {
if(dfs(i) == true) {
//存在组内环 直接返回
return new int[0];
}
}
color = new int[m];
//第二遍遍历 给组排序
for(int i = 0; i < m; ++i) {
if(dfsGroup(i) == true) {
//存在环 直接返回
return new int[0];
}
}
//根据所有组的结果构造答案
int[] ret = new int[n];
int index = 0;
for(int i : groupSort) {
for(int node : groupAns.get(i)) {
ret[index] = node;
++index;
}
}
return ret;
}
}
实现起来比想起来轻松多了
但是做出来是真的快乐