diff --git a/solution/3600-3699/3606.Coupon Code Validator/README.md b/solution/3600-3699/3606.Coupon Code Validator/README.md index 418bb16de8c1e..d586a85ca08fa 100644 --- a/solution/3600-3699/3606.Coupon Code Validator/README.md +++ b/solution/3600-3699/3606.Coupon Code Validator/README.md @@ -90,32 +90,212 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3600-3699/3606.Co -### 方法一 +### 方法一:模拟 + +我们可以直接模拟题目中的条件来筛选出有效的优惠券。具体步骤如下: + +1. **检查标识符**:对于每个优惠券的标识符,检查它是否非空,并且只包含字母、数字和下划线。 +2. **检查业务类别**:检查每个优惠券的业务类别是否属于给定的四个有效类别之一。 +3. **检查激活状态**:检查每个优惠券是否处于激活状态。 +4. **收集有效优惠券**:将所有满足上述条件的优惠券的 id 收集起来。 +5. **排序**:根据业务类别和标识符对有效优惠券进行排序。 +6. **返回结果**:返回排序后的有效优惠券的标识符列表。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$,其中 $n$ 是优惠券的数量。 #### Python3 ```python - +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] ``` #### Java ```java - +class Solution { + public List validateCoupons(String[] code, String[] businessLine, boolean[] isActive) { + List idx = new ArrayList<>(); + Set 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 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; + } +} ``` #### C++ ```cpp - +class Solution { +public: + vector validateCoupons(vector& code, vector& businessLine, vector& isActive) { + vector idx; + unordered_set 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 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; + } +}; ``` #### Go ```go +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 +} +``` +#### TypeScript + +```ts +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]); +} ``` diff --git a/solution/3600-3699/3606.Coupon Code Validator/README_EN.md b/solution/3600-3699/3606.Coupon Code Validator/README_EN.md index d87c733e4c078..6883dcc41ae6e 100644 --- a/solution/3600-3699/3606.Coupon Code Validator/README_EN.md +++ b/solution/3600-3699/3606.Coupon Code Validator/README_EN.md @@ -83,32 +83,212 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3600-3699/3606.Co -### Solution 1 +### Solution 1: Simulation + +We can directly simulate the conditions described in the problem to filter out valid coupons. The specific steps are as follows: + +1. **Check Identifier**: For each coupon's identifier, check whether it is non-empty and contains only letters, digits, and underscores. +2. **Check Business Category**: Check whether each coupon's business category belongs to one of the four valid categories. +3. **Check Activation Status**: Check whether each coupon is active. +4. **Collect Valid Coupons**: Collect the ids of all coupons that satisfy the above conditions. +5. **Sort**: Sort the valid coupons by business category and identifier. +6. **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. #### Python3 ```python - +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] ``` #### Java ```java - +class Solution { + public List validateCoupons(String[] code, String[] businessLine, boolean[] isActive) { + List idx = new ArrayList<>(); + Set 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 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; + } +} ``` #### C++ ```cpp - +class Solution { +public: + vector validateCoupons(vector& code, vector& businessLine, vector& isActive) { + vector idx; + unordered_set 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 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; + } +}; ``` #### Go ```go +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 +} +``` +#### TypeScript + +```ts +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]); +} ``` diff --git a/solution/3600-3699/3606.Coupon Code Validator/Solution.cpp b/solution/3600-3699/3606.Coupon Code Validator/Solution.cpp new file mode 100644 index 0000000000000..fa6f315cfe2ab --- /dev/null +++ b/solution/3600-3699/3606.Coupon Code Validator/Solution.cpp @@ -0,0 +1,38 @@ +class Solution { +public: + vector validateCoupons(vector& code, vector& businessLine, vector& isActive) { + vector idx; + unordered_set 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 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; + } +}; diff --git a/solution/3600-3699/3606.Coupon Code Validator/Solution.go b/solution/3600-3699/3606.Coupon Code Validator/Solution.go new file mode 100644 index 0000000000000..cfbcca0c20658 --- /dev/null +++ b/solution/3600-3699/3606.Coupon Code Validator/Solution.go @@ -0,0 +1,42 @@ +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 +} diff --git a/solution/3600-3699/3606.Coupon Code Validator/Solution.java b/solution/3600-3699/3606.Coupon Code Validator/Solution.java new file mode 100644 index 0000000000000..a1aa9facfe19d --- /dev/null +++ b/solution/3600-3699/3606.Coupon Code Validator/Solution.java @@ -0,0 +1,39 @@ +class Solution { + public List validateCoupons(String[] code, String[] businessLine, boolean[] isActive) { + List idx = new ArrayList<>(); + Set 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 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; + } +} diff --git a/solution/3600-3699/3606.Coupon Code Validator/Solution.py b/solution/3600-3699/3606.Coupon Code Validator/Solution.py new file mode 100644 index 0000000000000..c00bf99674476 --- /dev/null +++ b/solution/3600-3699/3606.Coupon Code Validator/Solution.py @@ -0,0 +1,19 @@ +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] diff --git a/solution/3600-3699/3606.Coupon Code Validator/Solution.ts b/solution/3600-3699/3606.Coupon Code Validator/Solution.ts new file mode 100644 index 0000000000000..0a3abdf1b5fc7 --- /dev/null +++ b/solution/3600-3699/3606.Coupon Code Validator/Solution.ts @@ -0,0 +1,30 @@ +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]); +}