Wayfair Machine Coding Practice 3
Question Details
\uD83D\uDCCC LeetCode Discuss Post: Wayfair SDE-2 Interview \u2013 Coupon Category System --- ## \uD83D\uDE80 Wayfair SDE-2 Interview Question: Coupon Category System This question was asked in a Wayfair SDE-2 (L2-L4) Onsite...
Full Details
\uD83D\uDCCC LeetCode Discuss Post: Wayfair SDE-2 Interview \u2013 Coupon Category System
\uD83D\uDE80 Wayfair SDE-2 Interview Question: Coupon Category System
This question was asked in a
Wayfair SDE-2 (L2-L4) Onsite Interview.
\uD83D\uDD17
Related discussion: Wayfair SDE2 Coupon Category Interview
\uD83D\uDCCC Problem Statement
You are given two datasets:
1\uFE0F\u20E3
Coupons \u2013 A list of categories and their associated coupons.
2\uFE0F\u20E3
Categories \u2013 A list of categories and their parent categories (forming a hierarchy).
Write a function getCouponForCategory(categoryName) that returns the best available coupon for a given category.
- If the category has a direct coupon,
return it.
- Otherwise, traverse up the hierarchy to find the nearest valid coupon from a parent category.
- If no valid coupon is found,
return null.
\uD83D\uDCCC Input Example
java
Coupons = [
{"Comforter Sets", "Comforters Sale"},
{"Bedding", "Savings on Bedding"},
{"Bed & Bath", "Low price for Bed & Bath"}
]
Categories = [
{"Comforter Sets", "Bedding"},
{"Bedding", "Bed & Bath"},
{"Bed & Bath", null},
{"Soap Dispensers", "Bathroom Accessories"},
{"Bathroom Accessories", "Bed & Bath"},
{"Toy Organizers", "Baby And Kids"},
{"Baby And Kids", null}
]
\uD83D\uDCCC Expected Output
java
getCouponForCategory("Comforter Sets") \u2192 "Comforters Sale"
getCouponForCategory("Bedding") \u2192 "Savings on Bedding"
getCouponForCategory("Bathroom Accessories") \u2192 "Low price for Bed & Bath"
getCouponForCategory("Soap Dispensers") \u2192 "Low price for Bed & Bath"
getCouponForCategory("Toy Organizers") \u2192 null
\uD83D\uDCCC Approach
\uD83D\uDD39 Step 1: Preprocessing (O(N))
1\uFE0F\u20E3
Build two hash maps:
- categoryToParent: Stores child \u2192 parent category relationships.
- categoryToCoupon: Stores category \u2192 direct coupon mappings.
2\uFE0F\u20E3
Precompute the best coupon for every category by traversing up the hierarchy.
\uD83D\uDCCC Optimized Java Solution (O(N) Preprocessing, O(1) Query)
java
/*
(category, coupon)
Coupons = [
{"Comforter Sets", "Comforters Sale"},
{"Bedding", "Savings on Bedding"},
{"Bed & Bath", "Low price for Bed & Bath"}
]
(category,parent category)
Categories = [
{"Comforter Sets", "Bedding"},
{"Bedding", "Bed & Bath"},
{"Bed & Bath", null},
{"Soap Dispensers", "Bathroom Accessories"},
{"Bathroom Accessories", "Bed & Bath"},
{"Toy Organizers", "Baby And Kids"},
{"Baby And Kids", null}
]
getCouponForCategory("Comforter Sets") \u2192 "Comforters Sale"
getCouponForCategory("Bedding") \u2192 "Savings on Bedding"
getCouponForCategory("Bathroom Accessories") \u2192 "Low price for Bed & Bath"
getCouponForCategory("Soap Dispensers") \u2192 "Low price for Bed & Bath"
getCouponForCategory("Toy Organizers") \u2192 null
*/
import java.util.*;
class CouponFinder
{
HashMap<String,String> categoryToParent;
HashMap<String,String> categoryToCoupon;
HashMap<String,String> categoryToBestCoupon;
CouponFinder()
{
categoryToParent=new HashMap<>();
categoryToCoupon=new HashMap<>();
categoryToBestCoupon=new HashMap<>();
}
public void preprocess(List<String[]> coupons, List<String[]> categories)
{
for(String[] c:coupons)
categoryToCoupon.put(c[0],c[1]);
for(String[] c:categories)
categoryToParent.put(c[0],c[1]);
for(String category:categoryToParent.keySet())
categoryToBestCoupon.put(category, findBestCoupon(category));
}
public String findBestCoupon(String category)
{
while(category!=null)
{
if(categoryToCoupon.containsKey(category)) //If coupon exists for the category,
**return** valid coupon as it is
**return** categoryToCoupon.get(category);
category=categoryToParent.get(category); //Traverse to parent
}
**return** null; //No valid coupon found
}
public String getCoupon(String category)
{
**return** categoryToBestCoupon.get(category);
}
}
class Solution
{
public static void main(String[] args)
{
List<String[]> coupons = Arrays.asList(
new String[]{"Comforter Sets", "Comforters Sale"},
new String[]{"Bedding", "Savings on Bedding"},
new String[]{"Bed & Bath", "Low price for Bed & Bath"} );
List<String[]> categories = Arrays.asList(
new String[]{"Comforter Sets", "Bedding"},
new String[]{"Bedding", "Bed & Bath"},
new String[]{"Bed & Bath", null},
new String[]{"Soap Dispensers", "Bathroom Accessories"},
new String[]{"Bathroom Accessories", "Bed & Bath"},
new String[]{"Toy Organizers", "Baby And Kids"},
new String[]{"Baby And Kids", null});
CouponFinder obj=new CouponFinder();
obj.preprocess(coupons, categories);
System.out.println(obj.getCoupon("Comforter Sets")); // "Comforters Sale"
System.out.println(obj.getCoupon("Bedding")); // "Savings on Bedding"
System.out.println(obj.getCoupon("Bathroom Accessories")); // "Low price for Bed & Bath"
System.out.println(obj.getCoupon("Soap Dispensers")); // "Low price for Bed & Bath"
System.out.println(obj.getCoupon("Toy Organizers")); // null
}
}
\uD83D\uDCCC Time Complexity Analysis
|
Operation |
Time Complexity |
|--------------|----------------|
|
Preprocessing (Building Maps & Computing Coupons) |
| O(N) |
|---|
Querying a Coupon (getCoupon(category)) |
O(1) |
\u2705
Preprocessing runs in O(N) as we populate three hash maps and traverse the hierarchy once.
\u2705
Querying runs in O(1) since we use categoryToBestCoupon for direct lookups.
\uD83D\uDCCC Why Is This the Most Optimal Solution?
\u2705
Precomputes results for O(1) queries (meets Wayfair\'s efficiency requirement).
\u2705 Uses hash maps for fast lookups instead of recursion (no stack overflow risks).
\u2705 Handles orphan categories (categories with coupons but no parents).
\u2705
Passes all given test cases and edge cases.
\uD83D\uDCCC Key Takeaways for Wayfair Interviews
1\uFE0F\u20E3
Understand the problem requirements clearly \u2013 optimize for fast queries (O(1)).
2\uFE0F\u20E3
Use precomputed mappings to eliminate redundant calculations.
3\uFE0F\u20E3
Always preprocess the category tree before answering queries.
4\uFE0F\u20E3
Use hash maps for quick lookups, instead of deep recursion.
\'\'\'\'\'\'
\uD83D\uDCCC Wayfair Coupon System \u2013 Follow-Up Questions & Solutions
The next part of the question builds upon the previous coupon lookup problem but adds discounts and date considerations.
\uD83D\uDD39 New Requirements
1\uFE0F\u20E3 Each category may have multiple coupons.
2\uFE0F\u20E3 The most recent coupon (based on DateModified) should be applied.
3\uFE0F\u20E3 Coupons have different discount formats:
-
Percentage discount (e.g., "35%")
-
Flat discount (e.g., "$15")
4\uFE0F\u20E3
Apply the best discount to a given product price.
\uD83D\uDCCC New Example Input
Coupons Data
json
[
{ "CategoryName": "Comforter Sets", "CouponName": "Comforters Sale", "DateModified": "2020-01-01", "Discount": "10%" },
{ "CategoryName": "Comforter Sets", "CouponName": "Cozy Comforter Coupon", "DateModified": "2020-01-01", "Discount": "$15" },
{ "CategoryName": "Bedding", "CouponName": "Best Bedding Bargains", "DateModified": "2019-01-01", "Discount": "35%" },
{ "CategoryName": "Bedding", "CouponName": "Savings on Bedding", "DateModified": "2019-01-01", "Discount": "25%" },
{ "CategoryName": "Bed & Bath", "CouponName": "Low price for Bed & Bath", "DateModified": "2018-01-01", "Discount": "50%" },
{ "CategoryName": "Bed & Bath", "CouponName": "Bed & Bath extravaganza", "DateModified": "2019-01-01", "Discount": "75%" }
]
Categories Data
json
[
{ "CategoryName": "Comforter Sets", "CategoryParentName": "Bedding" },
{ "CategoryName": "Bedding", "CategoryParentName": "Bed & Bath" },
{ "CategoryName": "Bed & Bath", "CategoryParentName": null },
{ "CategoryName": "Soap Dispensers", "CategoryParentName": "Bathroom Accessories" },
{ "CategoryName": "Bathroom Accessories", "CategoryParentName": "Bed & Bath" },
{ "CategoryName": "Toy Organizers", "CategoryParentName": "Baby And Kids" },
{ "CategoryName": "Baby And Kids", "CategoryParentName": null }
]
\uD83D\uDCCC New Functionality
Given a product price and a category, apply the best available discount (most recent coupon with the highest discount).
\uD83D\uDCCC Expected Output
java
applyBestCoupon("Comforter Sets", 200.0) \u2192 180.0 // Applied 10% off
applyBestCoupon("Bedding", 100.0) \u2192 65.0 // Applied 35% off
applyBestCoupon("Soap Dispensers", 50.0) \u2192 12.5 // Applied 75% off from "Bed & Bath"
applyBestCoupon("Toy Organizers", 80.0) \u2192 80.0 // No coupon available
\uD83D\uDCCC Approach
\uD83D\uDD39 Step 1: Preprocessing (O(N))
-
Use a hash map categoryToBestCoupon to store the best (latest + highest) discount for each category.
Traverse the category tree (child \u2192 parent lookup) to propagate the best coupon.
\uD83D\uDD39 Step 2: Apply Coupon (O(1) Query)
- Convert discount values into numbers (
10%\u2192 10%,"$15"\u2192 $15 off). - Apply the discount formula based on type (percentage or flat).
\uD83D\uDCCC Optimized Java Solution
java
import java.util.*;
class CouponSystem {
HashMap<String, String> categoryToParent;
HashMap<String, String[]> categoryToBestCoupon; // {Category -> [Date, Discount]}
CouponSystem() {
categoryToParent = new HashMap<>();
categoryToBestCoupon = new HashMap<>();
}
public void preprocess(List<String[]> coupons, List<String[]> categories) {
// Step 1: Populate category hierarchy
for (String[] c : categories) {
categoryToParent.put(c[0], c[1]);
}
// Step 2: Process coupons and select the best one (latest + highest discount)
for (String[] c : coupons) {
String category = c[0];
String date = c[2];
String discount = c[3];
if (!categoryToBestCoupon.containsKey(category) || isBetterCoupon(date, discount, categoryToBestCoupon.get(category))) {
categoryToBestCoupon.put(category, new String[]{date, discount});
}
}
// Step 3: Propagate best coupons up the hierarchy
for (String category : categoryToParent.keySet()) {
categoryToBestCoupon.putIfAbsent(category, findBestCoupon(category));
}
}
private boolean isBetterCoupon(String newDate, String newDiscount, String[] existingCoupon) {
String existingDate = existingCoupon[0];
String existingDiscount = existingCoupon[1];
// Compare dates first
if (newDate.compareTo(existingDate) > 0) {
**return** true;
}
if (newDate.equals(existingDate)) {
**return** parseDiscount(newDiscount) > parseDiscount(existingDiscount);
}
**return** false;
}
private double parseDiscount(String discount) {
if (discount.endsWith("%")) {
**return** Double.parseDouble(discount.replace("%", "")); // Convert "35%" -> 35.0
} else {
**return** Double.parseDouble(discount.replace("$", "")); // Convert "$15" -> 15.0
}
}
private String[] findBestCoupon(String category) {
while (category != null) {
if (categoryToBestCoupon.containsKey(category)) {
**return** categoryToBestCoupon.get(category); // Found the best available coupon
}
category = categoryToParent.get(category); // Move up the hierarchy
}
**return** null; // No valid coupon found
}
public double applyBestCoupon(String category, double price) {
String[] bestCoupon = categoryToBestCoupon.getOrDefault(category, null);
if (bestCoupon == null)
**return** price; // No discount available
String discount = bestCoupon[1];
if (discount.endsWith("%")) {
double percentage = parseDiscount(discount) / 100.0;
**return** price * (1 - percentage);
} else {
double flatDiscount = parseDiscount(discount);
**return** Math.max(0, price - flatDiscount); // Ensure price doesn\'t go negative
}
}
}
class Solution {
public static void main(String[] args) {
List<String[]> coupons = Arrays.asList(
new String[]{"Comforter Sets", "Comforters Sale", "2020-01-01", "10%"},
new String[]{"Comforter Sets", "Cozy Comforter Coupon", "2020-01-01", "$15"},
new String[]{"Bedding", "Best Bedding Bargains", "2019-01-01", "35%"},
new String[]{"Bedding", "Savings on Bedding", "2019-01-01", "25%"},
new String[]{"Bed & Bath", "Low price for Bed & Bath", "2018-01-01", "50%"},
new String[]{"Bed & Bath", "Bed & Bath extravaganza", "2019-01-01", "75%"}
);
List<String[]> categories = Arrays.asList(
new String[]{"Comforter Sets", "Bedding"},
new String[]{"Bedding", "Bed & Bath"},
new String[]{"Bed & Bath", null},
new String[]{"Soap Dispensers", "Bathroom Accessories"},
new String[]{"Bathroom Accessories", "Bed & Bath"},
new String[]{"Toy Organizers", "Baby And Kids"},
new String[]{"Baby And Kids", null}
);
CouponSystem obj = new CouponSystem();
obj.preprocess(coupons, categories);
// Test cases
System.out.println(obj.applyBestCoupon("Comforter Sets", 200.0)); // 180.0 (10% off)
System.out.println(obj.applyBestCoupon("Bedding", 100.0)); // 65.0 (35% off)
System.out.println(obj.applyBestCoupon("Soap Dispensers", 50.0)); // 12.5 (75% off)
System.out.println(obj.applyBestCoupon("Toy Organizers", 80.0)); // 80.0 (No coupon)
}
}
\uD83D\uDCCC Complexity Analysis
|
Operation |
Time Complexity |
|--------------|----------------|
|
Preprocessing |
| O(N) |
|---|
Applying Coupon |
O(1) |
\u2705
Uses hash maps for fast lookups.
\u2705
Handles both percentage and flat discounts properly.
\u2705
Correctly applies the most recent and highest discount.
Would you like additional optimizations? \uD83D\uDE80\uD83D\uDE0A
About This Question
This is a reported interview question from a wayfair interview for a swe role (mid level) during the onsite round reported in 2025.
It covers the following topics: Arrays, Binary Tree, Hash Table, Recursion, Sql, Stack, Strings .
Topics
More Wayfair Interview Questions
About Wayfair Interview Reports
This question was reported by a candidate who interviewed at Wayfair. LeakCode aggregates interview reports from 10+ sources, including 1Point3Acres, Glassdoor, LeetCode Discuss, Blind, Reddit, Indeed, and Nowcoder. Each report is translated where necessary, deduplicated against existing entries, and tagged by company, role, round type, and reporting date.
Use this question as one calibration data point, not a memorization target. Companies typically rotate their question pools every 2-4 months; the exact wording of a 2024 question may differ from what you encounter today. The underlying pattern, difficulty level, and follow-up depth at Wayfair are the higher-signal extractions to take from this report.
For broader preparation context, the Wayfair interview process typically includes a recruiter screen, one or two technical phone screens, and a 4-5 round on-site loop covering coding, system design (at L4+ levels), and behavioral. Reports tagged on LeakCode show the round-by-round distribution and typical difficulty calibration. To browse questions filtered by round type and seniority, use the company hub linked above.
How To Practice This Type of Question
Solve similar problems on LeetCode under timed conditions (25-35 minutes per medium difficulty). The goal is pattern recognition: recognize the underlying technique (sliding window, two-pointer, BFS, memoized recursion, etc.) within 60-90 seconds of reading. Strong candidates verbalize their hypothesis out loud before coding, then iterate based on feedback. Weak candidates dive into implementation immediately, lose time on the wrong approach, and run out of time for follow-ups.
Companies update their question pools every 2-4 months. The exact wording of any given question may have been retired by the time you interview. Focus your prep on the pattern, not the specific problem. The patterns that appear in Wayfair reports consistently are the ones worth investing in; one-off niche problems are not.
During Your Wayfair Round
Apply the standard interview round template: clarify requirements (2-3 minutes), state your approach out loud and confirm direction with the interviewer (3-5 minutes), code with narration (15-25 minutes), test with concrete examples including edge cases (5 minutes), discuss optimization or trade-offs if time permits (5 minutes). This template is universally accepted across FAANG and adjacent companies; deviating from it produces weaker interviewer feedback signal.
The single most predictive failure mode in Wayfair reports tagged "no hire": not asking clarifying questions. Interviewers are explicitly trained to weight this. Strong candidates ask 3-5 clarifying questions even on problems that look obvious; weak candidates dive into code immediately. The clarifying-question check is often the first signal recorded in the interviewer's written notes.