Skip to content

Commit 48f3a19

Browse files
authored
feat: add solutions to lc problem: No.3482 (#4151)
No.3482.Analyze Organization Hierarchy
1 parent 5a698f5 commit 48f3a19

File tree

4 files changed

+242
-2
lines changed

4 files changed

+242
-2
lines changed

solution/3400-3499/3482.Analyze Organization Hierarchy/README.md

+83-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ tags:
2020

2121
<pre>
2222
+----------------+---------+
23-
| Column Name | Type |
23+
| Column Name | Type |
2424
+----------------+---------+
2525
| employee_id | int |
2626
| employee_name | varchar |
@@ -151,7 +151,89 @@ manager_id is null for the top-level manager (CEO).
151151
#### MySQL
152152

153153
```sql
154+
# Write your MySQL query statement below
155+
WITH RECURSIVE
156+
level_cte AS (
157+
SELECT employee_id, manager_id, 1 AS level, salary FROM Employees
158+
UNION ALL
159+
SELECT a.employee_id, b.manager_id, level + 1, a.salary
160+
FROM
161+
level_cte a
162+
JOIN Employees b ON b.employee_id = a.manager_id
163+
),
164+
employee_with_level AS (
165+
SELECT a.employee_id, a.employee_name, a.salary, b.level
166+
FROM
167+
Employees a,
168+
(SELECT employee_id, level FROM level_cte WHERE manager_id IS NULL) b
169+
WHERE a.employee_id = b.employee_id
170+
)
171+
SELECT
172+
a.employee_id,
173+
a.employee_name,
174+
a.level,
175+
COALESCE(b.team_size, 0) AS team_size,
176+
a.salary + COALESCE(b.budget, 0) AS budget
177+
FROM
178+
employee_with_level a
179+
LEFT JOIN (
180+
SELECT manager_id AS employee_id, COUNT(*) AS team_size, SUM(salary) AS budget
181+
FROM level_cte
182+
WHERE manager_id IS NOT NULL
183+
GROUP BY manager_id
184+
) b
185+
ON a.employee_id = b.employee_id
186+
ORDER BY level, budget DESC, employee_name;
187+
```
154188

189+
#### Pandas
190+
191+
```python
192+
import pandas as pd
193+
194+
195+
def analyze_organization_hierarchy(employees: pd.DataFrame) -> pd.DataFrame:
196+
# 初始化 CEO (level 1)
197+
employees = employees.copy()
198+
employees["level"] = None
199+
ceo_id = employees.loc[employees["manager_id"].isna(), "employee_id"].values[0]
200+
employees.loc[employees["employee_id"] == ceo_id, "level"] = 1
201+
202+
# 递归计算层级
203+
def compute_levels(emp_df, level):
204+
next_level_ids = emp_df[emp_df["level"] == level]["employee_id"].tolist()
205+
if not next_level_ids:
206+
return
207+
emp_df.loc[emp_df["manager_id"].isin(next_level_ids), "level"] = level + 1
208+
compute_levels(emp_df, level + 1)
209+
210+
compute_levels(employees, 1)
211+
212+
# 计算 team_size 和 budget
213+
team_size = {eid: 0 for eid in employees["employee_id"]}
214+
budget = {
215+
eid: salary
216+
for eid, salary in zip(employees["employee_id"], employees["salary"])
217+
}
218+
219+
for eid in sorted(employees["employee_id"], reverse=True):
220+
manager_id = employees.loc[
221+
employees["employee_id"] == eid, "manager_id"
222+
].values[0]
223+
if pd.notna(manager_id):
224+
team_size[manager_id] += team_size[eid] + 1
225+
budget[manager_id] += budget[eid]
226+
227+
# 生成最终 DataFrame
228+
employees["team_size"] = employees["employee_id"].map(team_size)
229+
employees["budget"] = employees["employee_id"].map(budget)
230+
231+
# 按 level 升序,budget 降序,employee_name 升序排序
232+
employees = employees.sort_values(
233+
by=["level", "budget", "employee_name"], ascending=[True, False, True]
234+
)
235+
236+
return employees[["employee_id", "employee_name", "level", "team_size", "budget"]]
155237
```
156238

157239
<!-- tabs:end -->

solution/3400-3499/3482.Analyze Organization Hierarchy/README_EN.md

+78-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ tags:
2020

2121
<pre>
2222
+----------------+---------+
23-
| Column Name | Type |
23+
| Column Name | Type |
2424
+----------------+---------+
2525
| employee_id | int |
2626
| employee_name | varchar |
@@ -151,7 +151,84 @@ manager_id is null for the top-level manager (CEO).
151151
#### MySQL
152152

153153
```sql
154+
# Write your MySQL query statement below
155+
WITH RECURSIVE
156+
level_cte AS (
157+
SELECT employee_id, manager_id, 1 AS level, salary FROM Employees
158+
UNION ALL
159+
SELECT a.employee_id, b.manager_id, level + 1, a.salary
160+
FROM
161+
level_cte a
162+
JOIN Employees b ON b.employee_id = a.manager_id
163+
),
164+
employee_with_level AS (
165+
SELECT a.employee_id, a.employee_name, a.salary, b.level
166+
FROM
167+
Employees a,
168+
(SELECT employee_id, level FROM level_cte WHERE manager_id IS NULL) b
169+
WHERE a.employee_id = b.employee_id
170+
)
171+
SELECT
172+
a.employee_id,
173+
a.employee_name,
174+
a.level,
175+
COALESCE(b.team_size, 0) AS team_size,
176+
a.salary + COALESCE(b.budget, 0) AS budget
177+
FROM
178+
employee_with_level a
179+
LEFT JOIN (
180+
SELECT manager_id AS employee_id, COUNT(*) AS team_size, SUM(salary) AS budget
181+
FROM level_cte
182+
WHERE manager_id IS NOT NULL
183+
GROUP BY manager_id
184+
) b
185+
ON a.employee_id = b.employee_id
186+
ORDER BY level, budget DESC, employee_name;
187+
```
188+
189+
#### Pandas
190+
191+
```python
192+
import pandas as pd
193+
194+
def analyze_organization_hierarchy(employees: pd.DataFrame) -> pd.DataFrame:
195+
# Copy the input DataFrame to avoid modifying the original
196+
employees = employees.copy()
197+
employees['level'] = None
198+
199+
# Identify the CEO (level 1)
200+
ceo_id = employees.loc[employees['manager_id'].isna(), 'employee_id'].values[0]
201+
employees.loc[employees['employee_id'] == ceo_id, 'level'] = 1
202+
203+
# Recursively compute employee levels
204+
def compute_levels(emp_df, level):
205+
next_level_ids = emp_df[emp_df['level'] == level]['employee_id'].tolist()
206+
if not next_level_ids:
207+
return
208+
emp_df.loc[emp_df['manager_id'].isin(next_level_ids), 'level'] = level + 1
209+
compute_levels(emp_df, level + 1)
210+
211+
compute_levels(employees, 1)
212+
213+
# Initialize team size and budget dictionaries
214+
team_size = {eid: 0 for eid in employees['employee_id']}
215+
budget = {eid: salary for eid, salary in zip(employees['employee_id'], employees['salary'])}
216+
217+
# Compute team size and budget for each employee
218+
for eid in sorted(employees['employee_id'], reverse=True):
219+
manager_id = employees.loc[employees['employee_id'] == eid, 'manager_id'].values[0]
220+
if pd.notna(manager_id):
221+
team_size[manager_id] += team_size[eid] + 1
222+
budget[manager_id] += budget[eid]
223+
224+
# Map computed team size and budget to employees DataFrame
225+
employees['team_size'] = employees['employee_id'].map(team_size)
226+
employees['budget'] = employees['employee_id'].map(budget)
227+
228+
# Sort the final result by level (ascending), budget (descending), and employee name (ascending)
229+
employees = employees.sort_values(by=['level', 'budget', 'employee_name'], ascending=[True, False, True])
154230

231+
return employees[['employee_id', 'employee_name', 'level', 'team_size', 'budget']]
155232
```
156233

157234
<!-- tabs:end -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import pandas as pd
2+
3+
4+
def analyze_organization_hierarchy(employees: pd.DataFrame) -> pd.DataFrame:
5+
# Copy the input DataFrame to avoid modifying the original
6+
employees = employees.copy()
7+
employees["level"] = None
8+
9+
# Identify the CEO (level 1)
10+
ceo_id = employees.loc[employees["manager_id"].isna(), "employee_id"].values[0]
11+
employees.loc[employees["employee_id"] == ceo_id, "level"] = 1
12+
13+
# Recursively compute employee levels
14+
def compute_levels(emp_df, level):
15+
next_level_ids = emp_df[emp_df["level"] == level]["employee_id"].tolist()
16+
if not next_level_ids:
17+
return
18+
emp_df.loc[emp_df["manager_id"].isin(next_level_ids), "level"] = level + 1
19+
compute_levels(emp_df, level + 1)
20+
21+
compute_levels(employees, 1)
22+
23+
# Initialize team size and budget dictionaries
24+
team_size = {eid: 0 for eid in employees["employee_id"]}
25+
budget = {
26+
eid: salary
27+
for eid, salary in zip(employees["employee_id"], employees["salary"])
28+
}
29+
30+
# Compute team size and budget for each employee
31+
for eid in sorted(employees["employee_id"], reverse=True):
32+
manager_id = employees.loc[
33+
employees["employee_id"] == eid, "manager_id"
34+
].values[0]
35+
if pd.notna(manager_id):
36+
team_size[manager_id] += team_size[eid] + 1
37+
budget[manager_id] += budget[eid]
38+
39+
# Map computed team size and budget to employees DataFrame
40+
employees["team_size"] = employees["employee_id"].map(team_size)
41+
employees["budget"] = employees["employee_id"].map(budget)
42+
43+
# Sort the final result by level (ascending), budget (descending), and employee name (ascending)
44+
employees = employees.sort_values(
45+
by=["level", "budget", "employee_name"], ascending=[True, False, True]
46+
)
47+
48+
return employees[["employee_id", "employee_name", "level", "team_size", "budget"]]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Write your MySQL query statement below
2+
WITH RECURSIVE
3+
level_cte AS (
4+
SELECT employee_id, manager_id, 1 AS level, salary FROM Employees
5+
UNION ALL
6+
SELECT a.employee_id, b.manager_id, level + 1, a.salary
7+
FROM
8+
level_cte a
9+
JOIN Employees b ON b.employee_id = a.manager_id
10+
),
11+
employee_with_level AS (
12+
SELECT a.employee_id, a.employee_name, a.salary, b.level
13+
FROM
14+
Employees a,
15+
(SELECT employee_id, level FROM level_cte WHERE manager_id IS NULL) b
16+
WHERE a.employee_id = b.employee_id
17+
)
18+
SELECT
19+
a.employee_id,
20+
a.employee_name,
21+
a.level,
22+
COALESCE(b.team_size, 0) AS team_size,
23+
a.salary + COALESCE(b.budget, 0) AS budget
24+
FROM
25+
employee_with_level a
26+
LEFT JOIN (
27+
SELECT manager_id AS employee_id, COUNT(*) AS team_size, SUM(salary) AS budget
28+
FROM level_cte
29+
WHERE manager_id IS NOT NULL
30+
GROUP BY manager_id
31+
) b
32+
ON a.employee_id = b.employee_id
33+
ORDER BY level, budget DESC, employee_name;

0 commit comments

Comments
 (0)