Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using core interview patterns strategy.
Table: employees
+-------------+---------+ | Column Name | Type | +-------------+---------+ | employee_id | int | | name | varchar | +-------------+---------+ employee_id is the unique identifier for this table. Each row contains information about an employee.
Table: performance_reviews
+-------------+------+ | Column Name | Type | +-------------+------+ | review_id | int | | employee_id | int | | review_date | date | | rating | int | +-------------+------+ review_id is the unique identifier for this table. Each row represents a performance review for an employee. The rating is on a scale of 1-5 where 5 is excellent and 1 is poor.
Write a solution to find employees who have consistently improved their performance over their last three reviews.
3 review to be considered3 reviews must show strictly increasing ratings (each review better than the previous)3 reviews based on review_date for each employee3 reviewsReturn the result table ordered by improvement score in descending order, then by name in ascending order.
The result format is in the following example.
Example:
Input:
employees table:
+-------------+----------------+ | employee_id | name | +-------------+----------------+ | 1 | Alice Johnson | | 2 | Bob Smith | | 3 | Carol Davis | | 4 | David Wilson | | 5 | Emma Brown | +-------------+----------------+
performance_reviews table:
+-----------+-------------+-------------+--------+ | review_id | employee_id | review_date | rating | +-----------+-------------+-------------+--------+ | 1 | 1 | 2023-01-15 | 2 | | 2 | 1 | 2023-04-15 | 3 | | 3 | 1 | 2023-07-15 | 4 | | 4 | 1 | 2023-10-15 | 5 | | 5 | 2 | 2023-02-01 | 3 | | 6 | 2 | 2023-05-01 | 2 | | 7 | 2 | 2023-08-01 | 4 | | 8 | 2 | 2023-11-01 | 5 | | 9 | 3 | 2023-03-10 | 1 | | 10 | 3 | 2023-06-10 | 2 | | 11 | 3 | 2023-09-10 | 3 | | 12 | 3 | 2023-12-10 | 4 | | 13 | 4 | 2023-01-20 | 4 | | 14 | 4 | 2023-04-20 | 4 | | 15 | 4 | 2023-07-20 | 4 | | 16 | 5 | 2023-02-15 | 3 | | 17 | 5 | 2023-05-15 | 2 | +-----------+-------------+-------------+--------+
Output:
+-------------+----------------+-------------------+ | employee_id | name | improvement_score | +-------------+----------------+-------------------+ | 2 | Bob Smith | 3 | | 1 | Alice Johnson | 2 | | 3 | Carol Davis | 2 | +-------------+----------------+-------------------+
Explanation:
The output table is ordered by improvement_score in descending order, then by name in ascending order.
Problem summary: Table: employees +-------------+---------+ | Column Name | Type | +-------------+---------+ | employee_id | int | | name | varchar | +-------------+---------+ employee_id is the unique identifier for this table. Each row contains information about an employee. Table: performance_reviews +-------------+------+ | Column Name | Type | +-------------+------+ | review_id | int | | employee_id | int | | review_date | date | | rating | int | +-------------+------+ review_id is the unique identifier for this table. Each row represents a performance review for an employee. The rating is on a scale of 1-5 where 5 is excellent and 1 is poor. Write a solution to find employees who have consistently improved their performance over their last three reviews. An employee must have at least 3 review to be considered The employee's last 3 reviews must show strictly increasing ratings (each review better
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: General problem-solving
{"headers":{"employees":["employee_id","name"],"performance_reviews":["review_id","employee_id","review_date","rating"]},"rows":{"employees":[[1,"Alice Johnson"],[2,"Bob Smith"],[3,"Carol Davis"],[4,"David Wilson"],[5,"Emma Brown"]],"performance_reviews":[[1,1,"2023-01-15",2],[2,1,"2023-04-15",3],[3,1,"2023-07-15",4],[4,1,"2023-10-15",5],[5,2,"2023-02-01",3],[6,2,"2023-05-01",2],[7,2,"2023-08-01",4],[8,2,"2023-11-01",5],[9,3,"2023-03-10",1],[10,3,"2023-06-10",2],[11,3,"2023-09-10",3],[12,3,"2023-12-10",4],[13,4,"2023-01-20",4],[14,4,"2023-04-20",4],[15,4,"2023-07-20",4],[16,5,"2023-02-15",3],[17,5,"2023-05-15",2]]}}Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3580: Find Consistently Improving Employees
// Auto-generated Java example from py.
class Solution {
public void exampleSolution() {
}
}
// Reference (py):
// # Accepted solution for LeetCode #3580: Find Consistently Improving Employees
// import pandas as pd
//
//
// def find_consistently_improving_employees(
// employees: pd.DataFrame, performance_reviews: pd.DataFrame
// ) -> pd.DataFrame:
// performance_reviews = performance_reviews.sort_values(
// ["employee_id", "review_date"], ascending=[True, False]
// )
// performance_reviews["rn"] = (
// performance_reviews.groupby("employee_id").cumcount() + 1
// )
// performance_reviews["lag_rating"] = performance_reviews.groupby("employee_id")[
// "rating"
// ].shift(1)
// performance_reviews["delta"] = (
// performance_reviews["lag_rating"] - performance_reviews["rating"]
// )
// recent = performance_reviews[
// (performance_reviews["rn"] > 1) & (performance_reviews["rn"] <= 3)
// ]
// improvement = (
// recent.groupby("employee_id")
// .agg(
// improvement_score=("delta", "sum"),
// count=("delta", "count"),
// min_delta=("delta", "min"),
// )
// .reset_index()
// )
// improvement = improvement[
// (improvement["count"] == 2) & (improvement["min_delta"] > 0)
// ]
// result = improvement.merge(employees[["employee_id", "name"]], on="employee_id")
// result = result.sort_values(
// by=["improvement_score", "name"], ascending=[False, True]
// )
// return result[["employee_id", "name", "improvement_score"]]
// Accepted solution for LeetCode #3580: Find Consistently Improving Employees
// Auto-generated Go example from py.
func exampleSolution() {
}
// Reference (py):
// # Accepted solution for LeetCode #3580: Find Consistently Improving Employees
// import pandas as pd
//
//
// def find_consistently_improving_employees(
// employees: pd.DataFrame, performance_reviews: pd.DataFrame
// ) -> pd.DataFrame:
// performance_reviews = performance_reviews.sort_values(
// ["employee_id", "review_date"], ascending=[True, False]
// )
// performance_reviews["rn"] = (
// performance_reviews.groupby("employee_id").cumcount() + 1
// )
// performance_reviews["lag_rating"] = performance_reviews.groupby("employee_id")[
// "rating"
// ].shift(1)
// performance_reviews["delta"] = (
// performance_reviews["lag_rating"] - performance_reviews["rating"]
// )
// recent = performance_reviews[
// (performance_reviews["rn"] > 1) & (performance_reviews["rn"] <= 3)
// ]
// improvement = (
// recent.groupby("employee_id")
// .agg(
// improvement_score=("delta", "sum"),
// count=("delta", "count"),
// min_delta=("delta", "min"),
// )
// .reset_index()
// )
// improvement = improvement[
// (improvement["count"] == 2) & (improvement["min_delta"] > 0)
// ]
// result = improvement.merge(employees[["employee_id", "name"]], on="employee_id")
// result = result.sort_values(
// by=["improvement_score", "name"], ascending=[False, True]
// )
// return result[["employee_id", "name", "improvement_score"]]
# Accepted solution for LeetCode #3580: Find Consistently Improving Employees
import pandas as pd
def find_consistently_improving_employees(
employees: pd.DataFrame, performance_reviews: pd.DataFrame
) -> pd.DataFrame:
performance_reviews = performance_reviews.sort_values(
["employee_id", "review_date"], ascending=[True, False]
)
performance_reviews["rn"] = (
performance_reviews.groupby("employee_id").cumcount() + 1
)
performance_reviews["lag_rating"] = performance_reviews.groupby("employee_id")[
"rating"
].shift(1)
performance_reviews["delta"] = (
performance_reviews["lag_rating"] - performance_reviews["rating"]
)
recent = performance_reviews[
(performance_reviews["rn"] > 1) & (performance_reviews["rn"] <= 3)
]
improvement = (
recent.groupby("employee_id")
.agg(
improvement_score=("delta", "sum"),
count=("delta", "count"),
min_delta=("delta", "min"),
)
.reset_index()
)
improvement = improvement[
(improvement["count"] == 2) & (improvement["min_delta"] > 0)
]
result = improvement.merge(employees[["employee_id", "name"]], on="employee_id")
result = result.sort_values(
by=["improvement_score", "name"], ascending=[False, True]
)
return result[["employee_id", "name", "improvement_score"]]
// Accepted solution for LeetCode #3580: Find Consistently Improving Employees
// Rust example auto-generated from py reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (py):
// # Accepted solution for LeetCode #3580: Find Consistently Improving Employees
// import pandas as pd
//
//
// def find_consistently_improving_employees(
// employees: pd.DataFrame, performance_reviews: pd.DataFrame
// ) -> pd.DataFrame:
// performance_reviews = performance_reviews.sort_values(
// ["employee_id", "review_date"], ascending=[True, False]
// )
// performance_reviews["rn"] = (
// performance_reviews.groupby("employee_id").cumcount() + 1
// )
// performance_reviews["lag_rating"] = performance_reviews.groupby("employee_id")[
// "rating"
// ].shift(1)
// performance_reviews["delta"] = (
// performance_reviews["lag_rating"] - performance_reviews["rating"]
// )
// recent = performance_reviews[
// (performance_reviews["rn"] > 1) & (performance_reviews["rn"] <= 3)
// ]
// improvement = (
// recent.groupby("employee_id")
// .agg(
// improvement_score=("delta", "sum"),
// count=("delta", "count"),
// min_delta=("delta", "min"),
// )
// .reset_index()
// )
// improvement = improvement[
// (improvement["count"] == 2) & (improvement["min_delta"] > 0)
// ]
// result = improvement.merge(employees[["employee_id", "name"]], on="employee_id")
// result = result.sort_values(
// by=["improvement_score", "name"], ascending=[False, True]
// )
// return result[["employee_id", "name", "improvement_score"]]
// Accepted solution for LeetCode #3580: Find Consistently Improving Employees
// Auto-generated TypeScript example from py.
function exampleSolution(): void {
}
// Reference (py):
// # Accepted solution for LeetCode #3580: Find Consistently Improving Employees
// import pandas as pd
//
//
// def find_consistently_improving_employees(
// employees: pd.DataFrame, performance_reviews: pd.DataFrame
// ) -> pd.DataFrame:
// performance_reviews = performance_reviews.sort_values(
// ["employee_id", "review_date"], ascending=[True, False]
// )
// performance_reviews["rn"] = (
// performance_reviews.groupby("employee_id").cumcount() + 1
// )
// performance_reviews["lag_rating"] = performance_reviews.groupby("employee_id")[
// "rating"
// ].shift(1)
// performance_reviews["delta"] = (
// performance_reviews["lag_rating"] - performance_reviews["rating"]
// )
// recent = performance_reviews[
// (performance_reviews["rn"] > 1) & (performance_reviews["rn"] <= 3)
// ]
// improvement = (
// recent.groupby("employee_id")
// .agg(
// improvement_score=("delta", "sum"),
// count=("delta", "count"),
// min_delta=("delta", "min"),
// )
// .reset_index()
// )
// improvement = improvement[
// (improvement["count"] == 2) & (improvement["min_delta"] > 0)
// ]
// result = improvement.merge(employees[["employee_id", "name"]], on="employee_id")
// result = result.sort_values(
// by=["improvement_score", "name"], ascending=[False, True]
// )
// return result[["employee_id", "name", "improvement_score"]]
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.