LeetCode 2879 - Display the First Three Rows
The problem requires displaying the first three rows of a given DataFrame named employees. The DataFrame contains four columns: employeeid, name, department, and salary.
Difficulty: 🟢 Easy
Topics: —
Solution
Problem Understanding
The problem requires displaying the first three rows of a given DataFrame named employees. The DataFrame contains four columns: employee_id, name, department, and salary. The input represents a table of employee records, and the expected output is a subset of this table containing only the first three rows in their original order.
The problem is simple and straightforward because it does not involve filtering, sorting, or aggregation. The constraints are minimal: the DataFrame will have at least three rows (implied by the problem example), and the columns contain typical data types such as integers for employee_id and salary, and strings for name and department. The edge cases mostly involve DataFrames that have fewer than three rows, in which case the output should simply return all available rows without error. Another potential edge case is when the DataFrame is empty, which should return an empty DataFrame.
Approaches
The brute-force approach is to manually iterate through the DataFrame row by row, counting up to three rows and collecting them into a new DataFrame. While this works, it is unnecessarily verbose and ignores the built-in functionality provided by Pandas for selecting the top rows. The key insight for a more optimal solution is recognizing that Pandas provides the .head() method, which is explicitly designed for this purpose. Using .head(3) allows retrieving the first three rows efficiently without manually looping.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n) | O(3) | Iterate over each row until three are collected |
| Optimal | O(1) | O(1) | Use Pandas head(3) method which internally handles indexing |
Algorithm Walkthrough
- Access the DataFrame: Start by referencing the
employeesDataFrame passed into the function. No copying or transformation is needed at this stage. - Retrieve the first three rows: Call the
.head(3)method on the DataFrame. This efficiently selects the first three rows without needing to loop manually or check indices. - Return the result: The
.head()method produces a new DataFrame containing only the requested rows. Return this DataFrame directly.
Why it works: Pandas .head(n) guarantees returning the first n rows in their original order. If n exceeds the number of rows in the DataFrame, it simply returns all available rows without error. This ensures correctness in all cases, including small or empty DataFrames.
Python Solution
import pandas as pd
class Solution:
def displayTopThreeRows(self, employees: pd.DataFrame) -> pd.DataFrame:
# Use Pandas head() to get the first 3 rows
return employees.head(3)
In this implementation, the method displayTopThreeRows takes a DataFrame employees as input. The .head(3) method is called to retrieve the first three rows. This implementation directly maps to the algorithm steps: access the DataFrame, select the top three rows, and return the result. There is no need for explicit loops, conditionals, or manual slicing.
Go Solution
package main
import (
"github.com/kniren/gota/dataframe"
)
func DisplayTopThreeRows(employees dataframe.DataFrame) dataframe.DataFrame {
// Slice the DataFrame to include only the first 3 rows
n := 3
if employees.Nrow() < n {
n = employees.Nrow()
}
return employees.Subset(makeRange(0, n))
}
// Helper function to generate a range of indices
func makeRange(start, end int) []int {
r := make([]int, end-start)
for i := range r {
r[i] = start + i
}
return r
}
In Go, the Gota DataFrame library is used. Unlike Pandas, there is no built-in .Head() method, so we slice the DataFrame manually using the Subset method. The helper function makeRange generates the indices from 0 to 3, or fewer if the DataFrame has less than three rows. This handles the same edge cases as the Python version.
Worked Examples
Example 1
Input employees:
| employee_id | name | department | salary |
|---|---|---|---|
| 3 | Bob | Operations | 48675 |
| 90 | Alice | Sales | 11096 |
| 9 | Tatiana | Engineering | 33805 |
| 60 | Annabelle | InformationTechnology | 37678 |
| 49 | Jonathan | HumanResources | 23793 |
| 43 | Khaled | Administration | 40454 |
Step by step:
- Access the
employeesDataFrame. - Call
.head(3)(Python) orSubset([0,1,2])(Go). - Output:
| employee_id | name | department | salary |
|---|---|---|---|
| 3 | Bob | Operations | 48675 |
| 90 | Alice | Sales | 11096 |
| 9 | Tatiana | Engineering | 33805 |
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(1) | Accessing the first three rows is a constant-time operation in Pandas or via slicing in Gota. |
| Space | O(1) | No additional space beyond the new DataFrame of size at most 3 rows is used. |
Even though internally Pandas or Gota may create a view or shallow copy, the operation does not scale with n, so it is effectively constant time for our purposes.
Test Cases
import pandas as pd
# Standard case with more than 3 rows
df1 = pd.DataFrame({
"employee_id": [3, 90, 9, 60, 49, 43],
"name": ["Bob", "Alice", "Tatiana", "Annabelle", "Jonathan", "Khaled"],
"department": ["Operations", "Sales", "Engineering", "InformationTechnology", "HumanResources", "Administration"],
"salary": [48675, 11096, 33805, 37678, 23793, 40454]
})
assert Solution().displayTopThreeRows(df1).shape[0] == 3 # standard case
# Exactly 3 rows
df2 = pd.DataFrame({
"employee_id": [1,2,3],
"name": ["A","B","C"],
"department": ["X","Y","Z"],
"salary": [1000,2000,3000]
})
assert Solution().displayTopThreeRows(df2).shape[0] == 3 # boundary case
# Less than 3 rows
df3 = pd.DataFrame({
"employee_id": [5,6],
"name": ["D","E"],
"department": ["P","Q"],
"salary": [5000,6000]
})
assert Solution().displayTopThreeRows(df3).shape[0] == 2 # returns all rows
# Empty DataFrame
df4 = pd.DataFrame(columns=["employee_id","name","department","salary"])
assert Solution().displayTopThreeRows(df4).shape[0] == 0 # empty DataFrame
| Test | Why |
|---|---|
| More than 3 rows | Validates normal behavior and correct truncation |
| Exactly 3 rows | Checks boundary behavior for exact limit |
| Less than 3 rows | Ensures function does not error and returns all available rows |
| Empty DataFrame | Confirms function handles empty input gracefully |
Edge Cases
One important edge case is a DataFrame with fewer than three rows. A naive implementation that assumes at least three rows could throw an index out-of-range error, but using .head(3) or slicing up to the minimum of 3 and the DataFrame length prevents this.
Another edge case is an empty DataFrame. Any loop-based brute-force method must handle the zero-length scenario, whereas .head(3) naturally returns an empty DataFrame, simplifying the logic.
A third edge case involves very large DataFrames. Even though the dataset may contain millions of rows, retrieving only the first three rows is constant-time and does not depend on the total number of rows, ensuring efficiency and scalability.