|
| 1 | +# Coupon Code Validator |
| 2 | + |
| 3 | +**Difficulty:** Easy |
| 4 | +**Category:** String, Sorting, Simulation |
| 5 | +**Leetcode Link:** [Problem Link](https://leetcode.com/problems/coupon-code-validator/) |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## 📝 Introduction |
| 10 | + |
| 11 | +We are given three arrays of length `n` describing the properties of `n` coupons: |
| 12 | +- `code[i]`: A string representing the coupon identifier. |
| 13 | +- `businessLine[i]`: A string denoting the business category of the coupon. |
| 14 | +- `isActive[i]`: A boolean indicating whether the coupon is active. |
| 15 | + |
| 16 | +A coupon is valid if: |
| 17 | +1. `code[i]` is non-empty and contains only **alphanumeric characters** (`a-z, A-Z, 0-9`) and underscores (`_`). |
| 18 | +2. `businessLine[i]` is one of the following: `"electronics"`, `"grocery"`, `"pharmacy"`, `"restaurant"`. |
| 19 | +3. `isActive[i] == true`. |
| 20 | + |
| 21 | +We must return an array of valid coupon codes, **sorted first by businessLine** in the order: |
| 22 | +``` |
| 23 | +electronics → grocery → pharmacy → restaurant |
| 24 | +``` |
| 25 | +and then by `code` in lexicographical ascending order **within the same category**. |
| 26 | + |
| 27 | +--- |
| 28 | + |
| 29 | +## 💡 Approach & Key Insights |
| 30 | + |
| 31 | +1. **Validation**: |
| 32 | + - Ensure `code[i]` is not empty and contains only `[a-zA-Z0-9_]`. |
| 33 | + - Ensure `businessLine[i]` is in the allowed categories set. |
| 34 | + - Ensure `isActive[i]` is `true`. |
| 35 | + |
| 36 | +2. **Sorting**: |
| 37 | + - Create a custom order mapping for categories: |
| 38 | + ``` |
| 39 | + electronics → 0, grocery → 1, pharmacy → 2, restaurant → 3 |
| 40 | + ``` |
| 41 | + - Sort first by category order, then lexicographically by code. |
| 42 | +
|
| 43 | +3. **Output**: |
| 44 | + - Extract and return only the coupon codes from the valid list after sorting. |
| 45 | +
|
| 46 | +--- |
| 47 | +
|
| 48 | +## 🛠️ Breakdown of Approaches |
| 49 | +
|
| 50 | +### 1️⃣ Brute Force / Naive Approach |
| 51 | +
|
| 52 | +- **Explanation:** |
| 53 | + Loop over all coupons, validate each one, and store valid ones in a list. Sort using default string sorting and then reorder by category. |
| 54 | +- **Time Complexity:** O(n log n) — due to sorting. |
| 55 | +- **Space Complexity:** O(n) — storing valid coupons. |
| 56 | +
|
| 57 | +--- |
| 58 | +
|
| 59 | +### 2️⃣ Optimized Approach |
| 60 | +
|
| 61 | +- **Explanation:** |
| 62 | + While validating, store valid coupons as pairs `(businessLine, code)`. |
| 63 | + Sort using a custom comparator that compares category order first, then `code`. |
| 64 | +- **Time Complexity:** O(n log n) — sorting dominates. |
| 65 | +- **Space Complexity:** O(n) — storing valid coupons. |
| 66 | +
|
| 67 | +Example: |
| 68 | +``` |
| 69 | +code = ["SAVE20", "", "PHARMA5", "SAVE@20"] |
| 70 | +businessLine = ["restaurant", "grocery", "pharmacy", "restaurant"] |
| 71 | +isActive = [true, true, true, true] |
| 72 | + |
| 73 | +Valid coupons after filtering: |
| 74 | +[("restaurant", "SAVE20"), ("pharmacy", "PHARMA5")] |
| 75 | + |
| 76 | +After sorting by category order then code: |
| 77 | +[("pharmacy", "PHARMA5"), ("restaurant", "SAVE20")] |
| 78 | + |
| 79 | +Output: ["PHARMA5", "SAVE20"] |
| 80 | +``` |
| 81 | +
|
| 82 | +--- |
| 83 | +
|
| 84 | +## 📊 Complexity Analysis |
| 85 | +
|
| 86 | +| Approach | Time Complexity | Space Complexity | |
| 87 | +| ---------- | --------------- | ---------------- | |
| 88 | +| Validation | O(n) | O(n) | |
| 89 | +| Sorting | O(n log n) | O(n) | |
| 90 | +
|
| 91 | +--- |
| 92 | +
|
| 93 | +## 📌 Example Walkthroughs & Dry Runs |
| 94 | +
|
| 95 | +Example 1: |
| 96 | +``` |
| 97 | +Input: |
| 98 | +code = ["SAVE20", "", "PHARMA5", "SAVE@20"] |
| 99 | +businessLine = ["restaurant", "grocery", "pharmacy", "restaurant"] |
| 100 | +isActive = [true, true, true, true] |
| 101 | + |
| 102 | +Valid after filtering: |
| 103 | +[("restaurant", "SAVE20"), ("pharmacy", "PHARMA5")] |
| 104 | + |
| 105 | +Sorted: |
| 106 | +[("pharmacy", "PHARMA5"), ("restaurant", "SAVE20")] |
| 107 | + |
| 108 | +Output: |
| 109 | +["PHARMA5", "SAVE20"] |
| 110 | +``` |
| 111 | +
|
| 112 | +Example 2: |
| 113 | +``` |
| 114 | +Input: |
| 115 | +code = ["GROCERY15", "ELECTRONICS_50", "DISCOUNT10"] |
| 116 | +businessLine = ["grocery", "electronics", "invalid"] |
| 117 | +isActive = [false, true, true] |
| 118 | + |
| 119 | +Valid after filtering: |
| 120 | +[("electronics", "ELECTRONICS_50")] |
| 121 | + |
| 122 | +Output: |
| 123 | +["ELECTRONICS_50"] |
| 124 | +``` |
| 125 | +
|
| 126 | +--- |
| 127 | +
|
| 128 | +## 🔗 Additional Resources |
| 129 | +
|
| 130 | +- [Regular Expressions in Java](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html) |
| 131 | +- [Python: all() function](https://docs.python.org/3/library/functions.html#all) |
| 132 | +- [C++ isalnum function](https://www.cplusplus.com/reference/cctype/isalnum/) |
| 133 | +
|
| 134 | +--- |
| 135 | +
|
| 136 | +Author: Kailash Senthilkumar |
| 137 | +Date: 09/08/2025 |
0 commit comments