feat: add solutions to lc problem: No.3606 (#4558)

No.3606.Coupon Validator
This commit is contained in:
Libin YANG 2025-07-09 07:18:45 +08:00 committed by GitHub
parent 55d4ea1ff0
commit d7fddea9a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 530 additions and 2 deletions

View File

@ -90,32 +90,212 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3600-3699/3606.Co
<!-- solution:start -->
### 方法一
### 方法一:模拟
我们可以直接模拟题目中的条件来筛选出有效的优惠券。具体步骤如下:
1. **检查标识符**:对于每个优惠券的标识符,检查它是否非空,并且只包含字母、数字和下划线。
2. **检查业务类别**:检查每个优惠券的业务类别是否属于给定的四个有效类别之一。
3. **检查激活状态**:检查每个优惠券是否处于激活状态。
4. **收集有效优惠券**:将所有满足上述条件的优惠券的 id 收集起来。
5. **排序**:根据业务类别和标识符对有效优惠券进行排序。
6. **返回结果**:返回排序后的有效优惠券的标识符列表。
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$,其中 $n$ 是优惠券的数量。
<!-- tabs:start -->
#### 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<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;
}
}
```
#### C++
```cpp
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;
}
};
```
#### 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]);
}
```
<!-- tabs:end -->

View File

@ -83,32 +83,212 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3600-3699/3606.Co
<!-- solution:start -->
### 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.
<!-- tabs:start -->
#### 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<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;
}
}
```
#### C++
```cpp
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;
}
};
```
#### 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]);
}
```
<!-- tabs:end -->

View File

@ -0,0 +1,38 @@
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;
}
};

View File

@ -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
}

View File

@ -0,0 +1,39 @@
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;
}
}

View File

@ -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]

View File

@ -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]);
}