diff --git a/solution/3400-3499/3482.Analyze Organization Hierarchy/README.md b/solution/3400-3499/3482.Analyze Organization Hierarchy/README.md index e3799e5a173eb..0e7268f7b6ab4 100644 --- a/solution/3400-3499/3482.Analyze Organization Hierarchy/README.md +++ b/solution/3400-3499/3482.Analyze Organization Hierarchy/README.md @@ -20,7 +20,7 @@ tags:
+----------------+---------+ -| Column Name | Type | +| Column Name | Type | +----------------+---------+ | employee_id | int | | employee_name | varchar | @@ -151,7 +151,89 @@ manager_id is null for the top-level manager (CEO). #### MySQL ```sql +# Write your MySQL query statement below +WITH RECURSIVE + level_cte AS ( + SELECT employee_id, manager_id, 1 AS level, salary FROM Employees + UNION ALL + SELECT a.employee_id, b.manager_id, level + 1, a.salary + FROM + level_cte a + JOIN Employees b ON b.employee_id = a.manager_id + ), + employee_with_level AS ( + SELECT a.employee_id, a.employee_name, a.salary, b.level + FROM + Employees a, + (SELECT employee_id, level FROM level_cte WHERE manager_id IS NULL) b + WHERE a.employee_id = b.employee_id + ) +SELECT + a.employee_id, + a.employee_name, + a.level, + COALESCE(b.team_size, 0) AS team_size, + a.salary + COALESCE(b.budget, 0) AS budget +FROM + employee_with_level a + LEFT JOIN ( + SELECT manager_id AS employee_id, COUNT(*) AS team_size, SUM(salary) AS budget + FROM level_cte + WHERE manager_id IS NOT NULL + GROUP BY manager_id + ) b + ON a.employee_id = b.employee_id +ORDER BY level, budget DESC, employee_name; +``` +#### Pandas + +```python +import pandas as pd + + +def analyze_organization_hierarchy(employees: pd.DataFrame) -> pd.DataFrame: + # 初始化 CEO (level 1) + employees = employees.copy() + employees["level"] = None + ceo_id = employees.loc[employees["manager_id"].isna(), "employee_id"].values[0] + employees.loc[employees["employee_id"] == ceo_id, "level"] = 1 + + # 递归计算层级 + def compute_levels(emp_df, level): + next_level_ids = emp_df[emp_df["level"] == level]["employee_id"].tolist() + if not next_level_ids: + return + emp_df.loc[emp_df["manager_id"].isin(next_level_ids), "level"] = level + 1 + compute_levels(emp_df, level + 1) + + compute_levels(employees, 1) + + # 计算 team_size 和 budget + team_size = {eid: 0 for eid in employees["employee_id"]} + budget = { + eid: salary + for eid, salary in zip(employees["employee_id"], employees["salary"]) + } + + for eid in sorted(employees["employee_id"], reverse=True): + manager_id = employees.loc[ + employees["employee_id"] == eid, "manager_id" + ].values[0] + if pd.notna(manager_id): + team_size[manager_id] += team_size[eid] + 1 + budget[manager_id] += budget[eid] + + # 生成最终 DataFrame + employees["team_size"] = employees["employee_id"].map(team_size) + employees["budget"] = employees["employee_id"].map(budget) + + # 按 level 升序,budget 降序,employee_name 升序排序 + employees = employees.sort_values( + by=["level", "budget", "employee_name"], ascending=[True, False, True] + ) + + return employees[["employee_id", "employee_name", "level", "team_size", "budget"]] ``` diff --git a/solution/3400-3499/3482.Analyze Organization Hierarchy/README_EN.md b/solution/3400-3499/3482.Analyze Organization Hierarchy/README_EN.md index 9154e165d7b1f..15a6dbbeacb3b 100644 --- a/solution/3400-3499/3482.Analyze Organization Hierarchy/README_EN.md +++ b/solution/3400-3499/3482.Analyze Organization Hierarchy/README_EN.md @@ -20,7 +20,7 @@ tags:+----------------+---------+ -| Column Name | Type | +| Column Name | Type | +----------------+---------+ | employee_id | int | | employee_name | varchar | @@ -151,7 +151,84 @@ manager_id is null for the top-level manager (CEO). #### MySQL ```sql +# Write your MySQL query statement below +WITH RECURSIVE + level_cte AS ( + SELECT employee_id, manager_id, 1 AS level, salary FROM Employees + UNION ALL + SELECT a.employee_id, b.manager_id, level + 1, a.salary + FROM + level_cte a + JOIN Employees b ON b.employee_id = a.manager_id + ), + employee_with_level AS ( + SELECT a.employee_id, a.employee_name, a.salary, b.level + FROM + Employees a, + (SELECT employee_id, level FROM level_cte WHERE manager_id IS NULL) b + WHERE a.employee_id = b.employee_id + ) +SELECT + a.employee_id, + a.employee_name, + a.level, + COALESCE(b.team_size, 0) AS team_size, + a.salary + COALESCE(b.budget, 0) AS budget +FROM + employee_with_level a + LEFT JOIN ( + SELECT manager_id AS employee_id, COUNT(*) AS team_size, SUM(salary) AS budget + FROM level_cte + WHERE manager_id IS NOT NULL + GROUP BY manager_id + ) b + ON a.employee_id = b.employee_id +ORDER BY level, budget DESC, employee_name; +``` + +#### Pandas + +```python +import pandas as pd + +def analyze_organization_hierarchy(employees: pd.DataFrame) -> pd.DataFrame: + # Copy the input DataFrame to avoid modifying the original + employees = employees.copy() + employees['level'] = None + + # Identify the CEO (level 1) + ceo_id = employees.loc[employees['manager_id'].isna(), 'employee_id'].values[0] + employees.loc[employees['employee_id'] == ceo_id, 'level'] = 1 + + # Recursively compute employee levels + def compute_levels(emp_df, level): + next_level_ids = emp_df[emp_df['level'] == level]['employee_id'].tolist() + if not next_level_ids: + return + emp_df.loc[emp_df['manager_id'].isin(next_level_ids), 'level'] = level + 1 + compute_levels(emp_df, level + 1) + + compute_levels(employees, 1) + + # Initialize team size and budget dictionaries + team_size = {eid: 0 for eid in employees['employee_id']} + budget = {eid: salary for eid, salary in zip(employees['employee_id'], employees['salary'])} + + # Compute team size and budget for each employee + for eid in sorted(employees['employee_id'], reverse=True): + manager_id = employees.loc[employees['employee_id'] == eid, 'manager_id'].values[0] + if pd.notna(manager_id): + team_size[manager_id] += team_size[eid] + 1 + budget[manager_id] += budget[eid] + + # Map computed team size and budget to employees DataFrame + employees['team_size'] = employees['employee_id'].map(team_size) + employees['budget'] = employees['employee_id'].map(budget) + + # Sort the final result by level (ascending), budget (descending), and employee name (ascending) + employees = employees.sort_values(by=['level', 'budget', 'employee_name'], ascending=[True, False, True]) + return employees[['employee_id', 'employee_name', 'level', 'team_size', 'budget']] ``` diff --git a/solution/3400-3499/3482.Analyze Organization Hierarchy/Solution.py b/solution/3400-3499/3482.Analyze Organization Hierarchy/Solution.py new file mode 100644 index 0000000000000..013da93d2870c --- /dev/null +++ b/solution/3400-3499/3482.Analyze Organization Hierarchy/Solution.py @@ -0,0 +1,48 @@ +import pandas as pd + + +def analyze_organization_hierarchy(employees: pd.DataFrame) -> pd.DataFrame: + # Copy the input DataFrame to avoid modifying the original + employees = employees.copy() + employees["level"] = None + + # Identify the CEO (level 1) + ceo_id = employees.loc[employees["manager_id"].isna(), "employee_id"].values[0] + employees.loc[employees["employee_id"] == ceo_id, "level"] = 1 + + # Recursively compute employee levels + def compute_levels(emp_df, level): + next_level_ids = emp_df[emp_df["level"] == level]["employee_id"].tolist() + if not next_level_ids: + return + emp_df.loc[emp_df["manager_id"].isin(next_level_ids), "level"] = level + 1 + compute_levels(emp_df, level + 1) + + compute_levels(employees, 1) + + # Initialize team size and budget dictionaries + team_size = {eid: 0 for eid in employees["employee_id"]} + budget = { + eid: salary + for eid, salary in zip(employees["employee_id"], employees["salary"]) + } + + # Compute team size and budget for each employee + for eid in sorted(employees["employee_id"], reverse=True): + manager_id = employees.loc[ + employees["employee_id"] == eid, "manager_id" + ].values[0] + if pd.notna(manager_id): + team_size[manager_id] += team_size[eid] + 1 + budget[manager_id] += budget[eid] + + # Map computed team size and budget to employees DataFrame + employees["team_size"] = employees["employee_id"].map(team_size) + employees["budget"] = employees["employee_id"].map(budget) + + # Sort the final result by level (ascending), budget (descending), and employee name (ascending) + employees = employees.sort_values( + by=["level", "budget", "employee_name"], ascending=[True, False, True] + ) + + return employees[["employee_id", "employee_name", "level", "team_size", "budget"]] diff --git a/solution/3400-3499/3482.Analyze Organization Hierarchy/Solution.sql b/solution/3400-3499/3482.Analyze Organization Hierarchy/Solution.sql new file mode 100644 index 0000000000000..78677376e561d --- /dev/null +++ b/solution/3400-3499/3482.Analyze Organization Hierarchy/Solution.sql @@ -0,0 +1,33 @@ +# Write your MySQL query statement below +WITH RECURSIVE + level_cte AS ( + SELECT employee_id, manager_id, 1 AS level, salary FROM Employees + UNION ALL + SELECT a.employee_id, b.manager_id, level + 1, a.salary + FROM + level_cte a + JOIN Employees b ON b.employee_id = a.manager_id + ), + employee_with_level AS ( + SELECT a.employee_id, a.employee_name, a.salary, b.level + FROM + Employees a, + (SELECT employee_id, level FROM level_cte WHERE manager_id IS NULL) b + WHERE a.employee_id = b.employee_id + ) +SELECT + a.employee_id, + a.employee_name, + a.level, + COALESCE(b.team_size, 0) AS team_size, + a.salary + COALESCE(b.budget, 0) AS budget +FROM + employee_with_level a + LEFT JOIN ( + SELECT manager_id AS employee_id, COUNT(*) AS team_size, SUM(salary) AS budget + FROM level_cte + WHERE manager_id IS NOT NULL + GROUP BY manager_id + ) b + ON a.employee_id = b.employee_id +ORDER BY level, budget DESC, employee_name;