LeetCode Question · Feb 2025 · Los Angeles

Wayfair Machine Coding Practice 3

1 upvote 157 views 2 replies

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

Free preview — 6 questions shown. Unlock all Wayfair questions →

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 .

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.