Welcome to Subscribe On Youtube
3606. Coupon Code Validator
Description
You are given three arrays of length n
that describe the properties of n
coupons: code
, businessLine
, and isActive
. The ith
coupon has:
code[i]
: a string representing the coupon identifier.businessLine[i]
: a string denoting the business category of the coupon.isActive[i]
: a boolean indicating whether the coupon is currently active.
A coupon is considered valid if all of the following conditions hold:
code[i]
is non-empty and consists only of alphanumeric characters (a-z, A-Z, 0-9) and underscores (_
).businessLine[i]
is one of the following four categories:"electronics"
,"grocery"
,"pharmacy"
,"restaurant"
.isActive[i]
is true.
Return an array of the codes of all valid coupons, sorted first by their businessLine in the order: "electronics"
, "grocery"
, "pharmacy", "restaurant"
, and then by code in lexicographical (ascending) order within each category.
Example 1:
Input: code = ["SAVE20","","PHARMA5","SAVE@20"], businessLine = ["restaurant","grocery","pharmacy","restaurant"], isActive = [true,true,true,true]
Output: ["PHARMA5","SAVE20"]
Explanation:
- First coupon is valid.
- Second coupon has empty code (invalid).
- Third coupon is valid.
- Fourth coupon has special character
@
(invalid).
Example 2:
Input: code = ["GROCERY15","ELECTRONICS_50","DISCOUNT10"], businessLine = ["grocery","electronics","invalid"], isActive = [false,true,true]
Output: ["ELECTRONICS_50"]
Explanation:
- First coupon is inactive (invalid).
- Second coupon is valid.
- Third coupon has invalid business line (invalid).
Constraints:
n == code.length == businessLine.length == isActive.length
1 <= n <= 100
0 <= code[i].length, businessLine[i].length <= 100
code[i]
andbusinessLine[i]
consist of printable ASCII characters.isActive[i]
is eithertrue
orfalse
.
Solutions
Solution 1: Simulation
We can directly simulate the conditions described in the problem to filter out valid coupons. The specific steps are as follows:
- Check Identifier: For each coupon’s identifier, check whether it is non-empty and contains only letters, digits, and underscores.
- Check Business Category: Check whether each coupon’s business category belongs to one of the four valid categories.
- Check Activation Status: Check whether each coupon is active.
- Collect Valid Coupons: Collect the ids of all coupons that satisfy the above conditions.
- Sort: Sort the valid coupons by business category and identifier.
- Return Result: Return the list of identifiers of the sorted valid coupons.
The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$, where $n$ is the number of coupons.
-
class Solution { public List<String> validateCoupons(String[] code, String[] businessLine, boolean[] isActive) { List<Integer> idx = new ArrayList<>(); Set<String> bs = new HashSet<>(Arrays.asList("electronics", "grocery", "pharmacy", "restaurant")); for (int i = 0; i < code.length; i++) { if (isActive[i] && bs.contains(businessLine[i]) && check(code[i])) { idx.add(i); } } idx.sort((i, j) -> { int cmp = businessLine[i].compareTo(businessLine[j]); if (cmp != 0) { return cmp; } return code[i].compareTo(code[j]); }); List<String> ans = new ArrayList<>(); for (int i : idx) { ans.add(code[i]); } return ans; } private boolean check(String s) { if (s.isEmpty()) { return false; } for (char c : s.toCharArray()) { if (!Character.isLetterOrDigit(c) && c != '_') { return false; } } return true; } }
-
class Solution { public: vector<string> validateCoupons(vector<string>& code, vector<string>& businessLine, vector<bool>& isActive) { vector<int> idx; unordered_set<string> bs = {"electronics", "grocery", "pharmacy", "restaurant"}; for (int i = 0; i < code.size(); ++i) { const string& c = code[i]; const string& b = businessLine[i]; bool a = isActive[i]; if (a && bs.count(b) && check(c)) { idx.push_back(i); } } sort(idx.begin(), idx.end(), [&](int i, int j) { if (businessLine[i] != businessLine[j]) return businessLine[i] < businessLine[j]; return code[i] < code[j]; }); vector<string> ans; for (int i : idx) { ans.push_back(code[i]); } return ans; } private: bool check(const string& s) { if (s.empty()) return false; for (char c : s) { if (!isalnum(c) && c != '_') { return false; } } return true; } };
-
class Solution: def validateCoupons( self, code: List[str], businessLine: List[str], isActive: List[bool] ) -> List[str]: def check(s: str) -> bool: if not s: return False for c in s: if not (c.isalpha() or c.isdigit() or c == "_"): return False return True idx = [] bs = {"electronics", "grocery", "pharmacy", "restaurant"} for i, (c, b, a) in enumerate(zip(code, businessLine, isActive)): if a and b in bs and check(c): idx.append(i) idx.sort(key=lambda i: (businessLine[i], code[i])) return [code[i] for i in idx]
-
func validateCoupons(code []string, businessLine []string, isActive []bool) []string { idx := []int{} bs := map[string]struct{}{ "electronics": {}, "grocery": {}, "pharmacy": {}, "restaurant": {}, } check := func(s string) bool { if len(s) == 0 { return false } for _, c := range s { if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' { return false } } return true } for i := range code { if isActive[i] { if _, ok := bs[businessLine[i]]; ok && check(code[i]) { idx = append(idx, i) } } } sort.Slice(idx, func(i, j int) bool { if businessLine[idx[i]] != businessLine[idx[j]] { return businessLine[idx[i]] < businessLine[idx[j]] } return code[idx[i]] < code[idx[j]] }) ans := make([]string, 0, len(idx)) for _, i := range idx { ans = append(ans, code[i]) } return ans }
-
function validateCoupons(code: string[], businessLine: string[], isActive: boolean[]): string[] { const idx: number[] = []; const bs = new Set(['electronics', 'grocery', 'pharmacy', 'restaurant']); const check = (s: string): boolean => { if (s.length === 0) return false; for (let i = 0; i < s.length; i++) { const c = s[i]; if (!/[a-zA-Z0-9_]/.test(c)) { return false; } } return true; }; for (let i = 0; i < code.length; i++) { if (isActive[i] && bs.has(businessLine[i]) && check(code[i])) { idx.push(i); } } idx.sort((i, j) => { if (businessLine[i] !== businessLine[j]) { return businessLine[i] < businessLine[j] ? -1 : 1; } return code[i] < code[j] ? -1 : 1; }); return idx.map(i => code[i]); }