员工信息类
public static class Employee {
int happy; //每个员工都有happy值
List<Employee> nexts; //这名员工有哪些直接下级
public Employee(int h) {
this.happy = h;
nexts = new ArrayList<>();
}
}
公司的每个员工都符合Employee类的描述,整个公司的人员结构可以看做是一个标准的,没有环的多叉树(每个员工只有一个直接上级),树的头结点是公司唯一的老板,除老板之外的每个员工都有唯一的直接上级。叶结点是没有任何下属的基层员工(nexts列表为null),除基层员工外,每个员工都有1个上级和多个直接下级。
派对的最大欢乐值:
一个公司要举办Party,你可以决定哪些员工来,哪些员工不来,员工之间有上下级关系。规则:
给定一个多叉树的头结点,返回派对的最大欢乐值。
递归方式
以boss节点为例,最大值的情况有两种:1是boss来 2是boss不来, 如果boss不来的话,那么它的直属下级,可能来也可能不来,所以要求出boss来的最大值,和boss不来的最大值,并进行比较取较大的一个。 每个节点都可以看做是boss节点,如果当前节点不来,下级节点都可能来,可能不来。以此来构建Info类:
public static class Info {
int yes;
int no;
public Info(int y, int n) {
this.yes = y;
this.no = n;
}
}
public static int maxHappy1(Employee boss) {
if (boss == null) {
return 0;
}
Info allInfo = process1(boss);
//boss节点来的最大happy值和boss节点不来的最大happy值,取较大的一个
return Math.max(allInfo.no, allInfo.yes);
}
public static Info process1(Employee e) {
if (e == null) {
return new Info(0, 0);
}
//如果来,要加上当前节点的happy值
int yes = e.happy;
//如果不来,当前节点happy值为0
int no = 0;
for (Employee next : e.nexts) {
//递归调用process1
Info nextInfo = process1(next);
//如果当前节点来,那么要累加上下级节点不来时的happy值
yes += nextInfo.no;
//如果当前节点不来,那么下级节点可能来,也可能不来,取两个中的较大值
no += Math.max(nextInfo.no, nextInfo.yes);
}
//构建当前节点Info信息,供上层调用
return new Info(yes, no);
}
暴力方式
public static int maxHappy2(Employee boss) {
if (boss == null) {
return 0;
}
//boss为false 会先走else 也会进行累加
return process2(boss, false);
}
//e:当前节点
//up : true 代表当前节点来
//up : false 代表当前节点不来
public static int process2(Employee e, boolean up) {
if (up) {
int ans = 0;
for (Employee next : e.nexts) {
ans += process2(next, false);
}
return ans;
} else {
//当前节点happy值
int p1 = e.happy;
int p2 = 0;
for (Employee next : e.nexts) {
p1 += process2(next, true);
p2 += process2(next, false);
}
//取较大的一个
return Math.max(p1, p2);
}
}
生成Employee
给定下属节点最大值,最大层级,最大happy值,递归调用生成Employee。
public static Employee generateBoss(int maxHappy, int maxLevel, int maxNexts) {
if (Math.random() < 0.02) {
return null;
}
Employee boss = new Employee((int) (Math.random() * maxHappy));
generateNexts(boss, 1, maxLevel, maxNexts, maxHappy);
return boss;
}
public static void generateNexts(Employee boss, int level, int maxLevel, int maxNexts, int maxHappy) {
if (level > maxLevel) {
return;
}
int nextSize = (int) (Math.random() * maxNexts);
for (int i = 0; i < nextSize; i++) {
Employee e = new Employee((int) (Math.random() * maxHappy));
boss.nexts.add(e);
generateNexts(e, level + 1, maxLevel, maxNexts, maxHappy);
}
}
测试
public static void main(String[] args) {
int maxHappy = 100;
int nextSize = 10;
int maxLevel = 10;
int testNum = 1000;
for (int i = 0; i < testNum; i++) {
Employee boss = generateBoss(maxHappy, maxLevel, nextSize);
if (maxHappy1(boss) != maxHappy2(boss)){
System.out.println("Fuck!!");
break;
}
}
System.out.println("finish");
}