- Published on
HackerRank Frontend Interview questions with expert answers
- Authors
- Name
- Saurabh Mhatre

HackerRank Frontend Interview questions with expert answers
Hello everyone, today we will cover some interview questions in Frontend Developer interview rounds at HackerRank.
Founded in 2012, HackerRank is a technology company that focuses on competitive programming challenges for both consumers and businesses. On February 13, 2018, they had raised $30 million in Series C funding, led by JMI Equity.
If that’s got you excited then let’s start off with the actual questions
Q1. Design a 5-star rating system with half-star, hover, and click functionality
Creating a star rating system is a little challenging in itself. Creating one with a half-star rating system is even more challenging. We must break down the problem into smaller steps to solve it properly. So first let’s discuss the approach.
Approach
To simplify the problem, we are going to assign a half star if the star is clicked from the left-hand side and a full star if the star is clicked from the right side. Next, we need to handle the following cases:
- Render the stars dynamically: We first need to use an array to generate the required number of stars.
- Differentiate between full and half stars: Then we can detect whether the mouse is on the left (half-star) or right (full-star) of a star.
- Hover functionality: Next we preview the rating as the user hovers over the stars.
- Click functionality: We save the selected rating when a user clicks.
- Styling the stars: Finally, we will use some CSS to visually indicate the state of each star (full, half, or empty).
Implementation Steps
- Set Up the Component Structure We will set a React component that:
- Dynamically renders stars based on a
totalStarsprop. - Tracks the current rating and hover state using
useState.
2. Detect Hover and Click Position
To enable half-star ratings, we’ll use the offsetX property of the mouse event. This allows us to calculate if the user hovered over a star's left or right side.
3. Style the Stars
We’ll use CSS to style the stars and visually differentiate between full, half, and empty states. A linear gradient will be used to create the half-star effect.
Code Implementation
Star Rating Component Code:
import { useState } from "react";import "./StarRating.css";const StarRating = ({ totalStars = 5}) => { const [rating, setRating] = useState(0); // Store the selected rating const [hover, setHover] = useState(0); // Store the star hover rating // Determine if the hover or click is on the left (half-star) or right (full-star) side const getStarHoverValue = (event, index) => { const { offsetX, target } = event.nativeEvent; const isHalf = offsetX < target.offsetWidth / 2; // Check if cursor is on the left side of the star return isHalf ? index - 0.5 : index; }; // Handle hover event const handleMouseMove = (event, index) => { setHover(getStarHoverValue(event, index)); }; // Handle click event const handleStarClick = (event, index) => { setRating(getStarHoverValue(event, index)); }; // Reset hover when the mouse leaves const handleMouseLeave = () => { setHover(0); }; // render stars with rating and hover functionality const renderStars = () => { const stars = []; for (let i = 1; i <= totalStars; i++) { const index = i + 1; const isFull = hover >= index || rating >= index; const isHalf = hover === index - 0.5 || rating === index - 0.5; stars.push( <div key={index} className="star-container" onMouseMove={(e) => handleMouseMove(e, index)} onClick={(e) => handleStarClick(e, index)} > <span className={`star ${isFull ? "full" : isHalf ? "half" : "empty"}`} > ★ </span> </div> ); } return stars; } return ( <div className="star-rating" onMouseLeave={handleMouseLeave}> {renderStars()} </div> );};export default StarRating;
Explanation: We use rating and hover state variables to manage rating and hover state.
In getStarHoverValue function let’s cover some interesting elements:
event.nativeEvent: Provides the native DOM event, which contains low-level details like the cursor's position inside the target element.offsetX: We get the horizontal distance (in pixels) between the cursor and the left edge of the target element (the star in this case) from this value.
In this function, we check whether the cursor’s horizontal position (offsetX) is less than half the width of the star. If true, the cursor is on the left side (half-star); otherwise, it's on the right (full-star). If isHalf is true (cursor is on the left side), we subtract 0.5 from the index to represent a half-star rating (e.g., 2.5).
We use the above function handleMouseMove and handleStarClick functions.
Coming to the renderStars method, we have used a for loop to render our stars. We take the index and check for isFull and isHalf values.
If we carefully look at the logic below:
const isFull = hover >= index || rating >= index;const isHalf = hover === index - 0.5 || rating === index - 0.5;
We can see that hover comes before rating has higher precedence in or statement. This allows us to increment the star rating on hover first and the actual rating later meaning the star rating increases from the current value on hover. Once the onMouseMove event is triggered, setting the hover value to 0, the actual rating takes precedence since hover is now a falsy value(0) and the rating set by the user is visible. This allows us to set rating values when the mouse is not active on the stars.
Coming to the calculation part, the hover value is exactly index - 0.5, it means the cursor is hovering over the left half of the current star, so it should be displayed as half.
The onMouseMove function is used to detect and respond to the mouse cursor's movement over a specific star.
Next, we add some CSS to StarRating:
.star-rating { display: flex; gap: 5px; cursor: pointer;}.star-container { position: relative;}.star { font-size: 100px; color: #e4e5e9; /* Default grey for empty stars */ transition: color 0.2s ease, transform 0.2s ease;}.star.full { color: #f5c518; /* Gold color for full stars */}.star.half { background: linear-gradient(90deg, #f5c518 50%, #e4e5e9 50%); -webkit-background-clip: text; -webkit-text-fill-color: transparent;}.star.empty { color: #e4e5e9;}
In this case, star CSS styling for half star is a little tricky to remember but we can always ask the interviewer if it can be searched online since linear gradients are often allowed to be searched for in interviews.
Finally, we integrate star rating in the main App component as shown below:
import StarRating from "./components/StarRating/StarRating";function App() { return ( <> <h1>Rate Our Product</h1> <StarRating totalStars={5} /> </> )}export default App
The app preview is as shown below:

Component Preview
So this concludes the first question in the series. You can show some appreciation for the article and have a water break before we proceed ahead. If you are ready let’s proceed to the next question.
Q2. Set the entire matrix row and column as zeroes if the element at a given row/column is zero
We are given a 2D matrix and we need to set the entire row and column to zero if an element in the matrix is zero.
Example:
Input:
1, 3, 4 5, 0, 5 9, 8, 8
Output:
1, 0, 4 0, 0, 0 9, 0, 8
Approach:
- We first traverse the matrix and mark the rows and columns that need to be zeroed by checking elements which are aero.
- Then we use two arrays (
rowsandcols) to store the indices of the rows and columns that should be zeroed. - Finally, we iterate through the matrix and set the elements in the identified rows and columns to zero.
Implementation
function setZerosInRowsColumns(inputMatrix) { const rows = new Set(); const cols = new Set(); // Identify which rows and columns need to be filled with zeros for (let i = 0; i < inputMatrix.length; i++) { for (let j = 0; j < inputMatrix[i].length; j++) { if (inputMatrix[i][j] === 0) { rows.add(i); // Mark row for setting all zeros cols.add(j); // Mark column for setting all zeros } } } // Set the entire row and column to zero for (let i = 0; i < inputMatrix.length; i++) { for (let j = 0; j < inputMatrix[i].length; j++) { if (rows.has(i) || cols.has(j)) { inputMatrix[i][j] = 0; } } } return inputMatrix;}// Example usageconst inputMatrix = [ [1, 3, 4], [5, 0, 5], [9, 8, 8]];console.log("Output Matrix:",setZerosInRowsColumns(inputMatrix));/*Output:"Output Matrix:"[[1,0,4],[0,0,0],[9,0,8]]*/
Code Explanation:
- We use a
Setto store the rows and columns that need to be filled with zeros becauseSetensures that each element is unique. - In the first loop, we check each element of the matrix. If it’s zero, we add the row index and column index to the respective sets so that we can fill them with zeros later.
- In the second loop, we iterate through the matrix again and set the element to zero if its row or column is in the respective set.
Time Complexity:
The time complexity of the above approach is O(n²) since we use a nested for loop in both steps.
This concludes the second question in the series. You can add this article to your reading list and come back later after a short break.
If you are ready for the next question then let's proceed ahead.
Q3. Google Sheet mock implementation using ReactJS
In such questions we are not supposed to design a full-fledged app but only a basic mockup with simple functionality. In our case, we are simply going to create a row and column grid with the functionality to add columns and rows as shown below:

Component Preview
The buttons allow us to add rows and columns dynamically. With that in mind let's proceed ahead.
Approach
Building sheet The first problem that we need to figure out is representation and handling the data in the sheet. If we think carefully we come to know that sheet is a large 2D matrix with rows and columns. So we can use a 2D array to store and represent the sheet. Each sub-array in the array corresponds to a row, and each element in the sub-array corresponds to a cell. Example:
const data = [ ["A1", "B1", "C1"], ["A2", "B2", "C2"],];
This represents a 2-row, 3-column grid.
Dynamic Row and Column Management: Next, we need to figure out how to add rows and columns to the sheet or 2D array above. Add Row: We can simply append a new array with empty strings after the existing sub-arrays in the 2D array to add a new row. Add Column: We need to add an empty string to each existing row(subarray) to add a new column.
Editable Cells: We will represent each cell in the 2D array as an input field. Editing the input will update the corresponding value in the 2D array.
Code Implementation
Let's create a Sheet Component with below code:
import { useState } from "react";import "./Sheet.css";const Sheet = () => { // State to store the sheet data const [sheetData, setSheetData] = useState([ ["", "", ""], ["", "", ""], ["", "", ""], ]); // Adds a new row at the bottom of the grid const addSheetRow = () => { setSheetData([...sheetData, Array(sheetData[0].length).fill("")]); }; // Adds a new column at the end of each row const addSheetColumn = () => { setSheetData(sheetData.map((row) => [...row, ""])); }; // Updates the value of a specific cell const updateSheetCell = (rowIndex, colIndex, value) => { const updatedSheetData = sheetData.map((row, rIdx) => row.map((cell, cIdx) => (rIdx === rowIndex && cIdx === colIndex ? value : cell)) ); setSheetData(updatedSheetData); }; return ( <div> {/* Render the grid */} <div className="grid"> {sheetData.map((row, rowIndex) => ( <div key={rowIndex} className="row"> {row.map((cell, colIndex) => ( <input key={`${rowIndex}-${colIndex}`} value={cell} onChange={(e) => updateSheetCell(rowIndex, colIndex, e.target.value)} className="cell" /> ))} </div> ))} </div> {/* Buttons to add rows and columns */} <div className="controls"> <button onClick={addSheetRow}>Add Row</button> <button onClick={addSheetColumn}>Add Column</button> </div> </div> );};export default Sheet;
Code Explanation
First, we have used a 2D array to represent the initial 3x3 grid.
// State to store the sheet data const [sheetData, setSheetData] = useState([ ["", "", ""], ["", "", ""], ["", "", ""], ]);
We have used state variable to update rows, columns and sheet data dynamically.
Next in the addSheetRow method, we append a new array with empty data at the end of existing sub-arrays to insert a new row.
In the addSheetColumn method we iterate over each subarray to append an empty string at the end to insert a new column.
In the updateSheetCell method, we iterate over subarrays again and only update the target cell based on the passed target row and column index and leave the rest of the cells as it is.
In the return function, we simply render the sheet based on 2d array values and have button click listeners for row and column addition.
Next, we add some styling to the Sheet:
.grid { display: flex; flex-direction: column; align-items: start; gap: 5px; margin: 20px;}.row { display: flex;}.cell { width: 100px; height: 30px; border: 1px solid #ccc; text-align: center;}.controls { margin: 20px; display: flex; gap: 10px;}button { padding: 10px 15px; font-size: 14px; cursor: pointer; border: 1px solid #007bff; background-color: #007bff; color: #fff; border-radius: 5px;}button:hover { background-color: #0056b3;}
Now we can import the Sheet component into the main App component:
import './App.css'import Sheet from "./components/Sheet/Sheet";function App() { return ( <> <h1>Google Sheets Mock</h1> <Sheet /> </> )}export default App
With this, you can see and interact with the sheet as shown in the component preview at the beginning of this question.
That was the end of the list of questions asked in Frontend Developer Interview rounds at HackerRank. If you found this article useful then show some appreciation for more such articles in your feed. That’s it from my end for today. See you all in the next article. Goodbye 👋
Questions Reference: AmbitionBox, Glassdoor
