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.
Break down a hard problem into reliable checkpoints, edge-case handling, and complexity trade-offs.
Table: course_completions
+-------------------+---------+ | Column Name | Type | +-------------------+---------+ | user_id | int | | course_id | int | | course_name | varchar | | completion_date | date | | course_rating | int | +-------------------+---------+ (user_id, course_id) is the combination of columns with unique values for this table. Each row represents a completed course by a user with their rating (1-5 scale).
Write a solution to identify skill mastery pathways by analyzing course completion sequences among top-performing students:
5 courses with an average rating of 4 or higher).Course A → Course B) taken by these students.Return the result table ordered by pair frequency in descending order and then by first course name and second course name in ascending order.
The result format is in the following example.
Example:
Input:
course_completions table:
+---------+-----------+------------------+-----------------+---------------+ | user_id | course_id | course_name | completion_date | course_rating | +---------+-----------+------------------+-----------------+---------------+ | 1 | 101 | Python Basics | 2024-01-05 | 5 | | 1 | 102 | SQL Fundamentals | 2024-02-10 | 4 | | 1 | 103 | JavaScript | 2024-03-15 | 5 | | 1 | 104 | React Basics | 2024-04-20 | 4 | | 1 | 105 | Node.js | 2024-05-25 | 5 | | 1 | 106 | Docker | 2024-06-30 | 4 | | 2 | 101 | Python Basics | 2024-01-08 | 4 | | 2 | 104 | React Basics | 2024-02-14 | 5 | | 2 | 105 | Node.js | 2024-03-20 | 4 | | 2 | 106 | Docker | 2024-04-25 | 5 | | 2 | 107 | AWS Fundamentals | 2024-05-30 | 4 | | 3 | 101 | Python Basics | 2024-01-10 | 3 | | 3 | 102 | SQL Fundamentals | 2024-02-12 | 3 | | 3 | 103 | JavaScript | 2024-03-18 | 3 | | 3 | 104 | React Basics | 2024-04-22 | 2 | | 3 | 105 | Node.js | 2024-05-28 | 3 | | 4 | 101 | Python Basics | 2024-01-12 | 5 | | 4 | 108 | Data Science | 2024-02-16 | 5 | | 4 | 109 | Machine Learning | 2024-03-22 | 5 | +---------+-----------+------------------+-----------------+---------------+
Output:
+------------------+------------------+------------------+ | first_course | second_course | transition_count | +------------------+------------------+------------------+ | Node.js | Docker | 2 | | React Basics | Node.js | 2 | | Docker | AWS Fundamentals | 1 | | JavaScript | React Basics | 1 | | Python Basics | React Basics | 1 | | Python Basics | SQL Fundamentals | 1 | | SQL Fundamentals | JavaScript | 1 | +------------------+------------------+------------------+
Explanation:
Results are ordered by transition_count in descending order, then by first_course in ascending order, and then by second_course in ascending order.
Problem summary: Table: course_completions +-------------------+---------+ | Column Name | Type | +-------------------+---------+ | user_id | int | | course_id | int | | course_name | varchar | | completion_date | date | | course_rating | int | +-------------------+---------+ (user_id, course_id) is the combination of columns with unique values for this table. Each row represents a completed course by a user with their rating (1-5 scale). Write a solution to identify skill mastery pathways by analyzing course completion sequences among top-performing students: Consider only top-performing students (those who completed at least 5 courses with an average rating of 4 or higher). For each top performer, identify the sequence of courses they completed in chronological order. Find all consecutive course pairs (Course A → Course B) taken by these students. Return the pair frequency, identifying which course
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: General problem-solving
{"headers":{"course_completions":["user_id","course_id","course_name","completion_date","course_rating"]},"rows":{"course_completions":[[1,101,"Python Basics","2024-01-05",5],[1,102,"SQL Fundamentals","2024-02-10",4],[1,103,"JavaScript","2024-03-15",5],[1,104,"React Basics","2024-04-20",4],[1,105,"Node.js","2024-05-25",5],[1,106,"Docker","2024-06-30",4],[2,101,"Python Basics","2024-01-08",4],[2,104,"React Basics","2024-02-14",5],[2,105,"Node.js","2024-03-20",4],[2,106,"Docker","2024-04-25",5],[2,107,"AWS Fundamentals","2024-05-30",4],[3,101,"Python Basics","2024-01-10",3],[3,102,"SQL Fundamentals","2024-02-12",3],[3,103,"JavaScript","2024-03-18",3],[3,104,"React Basics","2024-04-22",2],[3,105,"Node.js","2024-05-28",3],[4,101,"Python Basics","2024-01-12",5],[4,108,"Data Science","2024-02-16",5],[4,109,"Machine Learning","2024-03-22",5]]}}Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3764: Most Common Course Pairs
// Auto-generated Java example from py.
class Solution {
public void exampleSolution() {
}
}
// Reference (py):
// # Accepted solution for LeetCode #3764: Most Common Course Pairs
// import pandas as pd
//
//
// def topLearnerCourseTransitions(course_completions: pd.DataFrame) -> pd.DataFrame:
// grp = course_completions.groupby("user_id")
// top_students = grp.filter(
// lambda df: df.shape[0] >= 5 and df["course_rating"].mean() >= 4
// )["user_id"].unique()
//
// df = course_completions[course_completions["user_id"].isin(top_students)].copy()
// df = df.sort_values(["user_id", "completion_date"])
// df["second_course"] = df.groupby("user_id")["course_name"].shift(-1)
// df["first_course"] = df["course_name"]
//
// pairs = df[df["second_course"].notna()][["first_course", "second_course"]]
//
// result = (
// pairs.groupby(["first_course", "second_course"])
// .size()
// .reset_index(name="transition_count")
// .sort_values(
// ["transition_count", "first_course", "second_course"],
// ascending=[False, True, True],
// key=lambda col: col.str.lower() if col.dtype == "object" else col,
// )
// .reset_index(drop=True)
// )
//
// return result
// Accepted solution for LeetCode #3764: Most Common Course Pairs
// Auto-generated Go example from py.
func exampleSolution() {
}
// Reference (py):
// # Accepted solution for LeetCode #3764: Most Common Course Pairs
// import pandas as pd
//
//
// def topLearnerCourseTransitions(course_completions: pd.DataFrame) -> pd.DataFrame:
// grp = course_completions.groupby("user_id")
// top_students = grp.filter(
// lambda df: df.shape[0] >= 5 and df["course_rating"].mean() >= 4
// )["user_id"].unique()
//
// df = course_completions[course_completions["user_id"].isin(top_students)].copy()
// df = df.sort_values(["user_id", "completion_date"])
// df["second_course"] = df.groupby("user_id")["course_name"].shift(-1)
// df["first_course"] = df["course_name"]
//
// pairs = df[df["second_course"].notna()][["first_course", "second_course"]]
//
// result = (
// pairs.groupby(["first_course", "second_course"])
// .size()
// .reset_index(name="transition_count")
// .sort_values(
// ["transition_count", "first_course", "second_course"],
// ascending=[False, True, True],
// key=lambda col: col.str.lower() if col.dtype == "object" else col,
// )
// .reset_index(drop=True)
// )
//
// return result
# Accepted solution for LeetCode #3764: Most Common Course Pairs
import pandas as pd
def topLearnerCourseTransitions(course_completions: pd.DataFrame) -> pd.DataFrame:
grp = course_completions.groupby("user_id")
top_students = grp.filter(
lambda df: df.shape[0] >= 5 and df["course_rating"].mean() >= 4
)["user_id"].unique()
df = course_completions[course_completions["user_id"].isin(top_students)].copy()
df = df.sort_values(["user_id", "completion_date"])
df["second_course"] = df.groupby("user_id")["course_name"].shift(-1)
df["first_course"] = df["course_name"]
pairs = df[df["second_course"].notna()][["first_course", "second_course"]]
result = (
pairs.groupby(["first_course", "second_course"])
.size()
.reset_index(name="transition_count")
.sort_values(
["transition_count", "first_course", "second_course"],
ascending=[False, True, True],
key=lambda col: col.str.lower() if col.dtype == "object" else col,
)
.reset_index(drop=True)
)
return result
// Accepted solution for LeetCode #3764: Most Common Course Pairs
// 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 #3764: Most Common Course Pairs
// import pandas as pd
//
//
// def topLearnerCourseTransitions(course_completions: pd.DataFrame) -> pd.DataFrame:
// grp = course_completions.groupby("user_id")
// top_students = grp.filter(
// lambda df: df.shape[0] >= 5 and df["course_rating"].mean() >= 4
// )["user_id"].unique()
//
// df = course_completions[course_completions["user_id"].isin(top_students)].copy()
// df = df.sort_values(["user_id", "completion_date"])
// df["second_course"] = df.groupby("user_id")["course_name"].shift(-1)
// df["first_course"] = df["course_name"]
//
// pairs = df[df["second_course"].notna()][["first_course", "second_course"]]
//
// result = (
// pairs.groupby(["first_course", "second_course"])
// .size()
// .reset_index(name="transition_count")
// .sort_values(
// ["transition_count", "first_course", "second_course"],
// ascending=[False, True, True],
// key=lambda col: col.str.lower() if col.dtype == "object" else col,
// )
// .reset_index(drop=True)
// )
//
// return result
// Accepted solution for LeetCode #3764: Most Common Course Pairs
// Auto-generated TypeScript example from py.
function exampleSolution(): void {
}
// Reference (py):
// # Accepted solution for LeetCode #3764: Most Common Course Pairs
// import pandas as pd
//
//
// def topLearnerCourseTransitions(course_completions: pd.DataFrame) -> pd.DataFrame:
// grp = course_completions.groupby("user_id")
// top_students = grp.filter(
// lambda df: df.shape[0] >= 5 and df["course_rating"].mean() >= 4
// )["user_id"].unique()
//
// df = course_completions[course_completions["user_id"].isin(top_students)].copy()
// df = df.sort_values(["user_id", "completion_date"])
// df["second_course"] = df.groupby("user_id")["course_name"].shift(-1)
// df["first_course"] = df["course_name"]
//
// pairs = df[df["second_course"].notna()][["first_course", "second_course"]]
//
// result = (
// pairs.groupby(["first_course", "second_course"])
// .size()
// .reset_index(name="transition_count")
// .sort_values(
// ["transition_count", "first_course", "second_course"],
// ascending=[False, True, True],
// key=lambda col: col.str.lower() if col.dtype == "object" else col,
// )
// .reset_index(drop=True)
// )
//
// return result
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.