diff --git a/lcci/16.18.Pattern Matching/README.md b/lcci/16.18.Pattern Matching/README.md index 4b8575004e3b5..01bd13688ac55 100644 --- a/lcci/16.18.Pattern Matching/README.md +++ b/lcci/16.18.Pattern Matching/README.md @@ -5,6 +5,7 @@ ## 题目描述 +
你有两个字符串,即pattern和value。 pattern字符串由字母"a"和"b"组成,用于描述字符串中的模式。例如,字符串"catcatgocatgo"匹配模式"aabab"(其中"cat"是"a","go"是"b"),该字符串也匹配像"a"、"ab"和"b"这样的模式。但需注意"a"和"b"不能同时表示相同的字符串。编写一个方法判断value字符串是否匹配pattern字符串。
示例 1:
输入: pattern = "abba", value = "dogcatcatdog"
@@ -33,6 +34,19 @@
## 解法
+
+**方法一:枚举**
+
+我们先统计出模式串 $pattern$ 中 `'a'` 和 `'b'` 的个数,分别为 $cnt[0]$ 和 $cnt[1]$。记字符串 $value$ 的长度为 $n$。
+
+如果 $cnt[0]=0$,说明模式串中只包含字符 `'b'`,那么我们需要判断 $n$ 是否是 $cnt[1]$ 的倍数,以及 $value$ 是否可以分割成 $cnt[1]$ 个长度为 $n/cnt[1]$ 的子串,且这些子串都相同。如果不满足,直接返回 $false$ 即可。
+
+如果 $cnt[1]=0$,说明模式串中只包含字符 `'a'`,那么我们需要判断 $n$ 是否是 $cnt[0]$ 的倍数,以及 $value$ 是否可以分割成 $cnt[0]$ 个长度为 $n/cnt[0]$ 的子串,且这些子串都相同。如果不满足,直接返回 $false$ 即可。
+
+接下来,我们记字符 `'a'` 所匹配的字符串的长度 $la$,字符 `'b'` 所匹配的字符串的长度 $lb$。那么有 $la \times cnt[0] + lb \times cnt[1] = n$。如果我们枚举 $la$,就可以知道 $lb$ 的值了。因此我们可以枚举 $la$,只需要判断是否存在一个整数 $lb$,满足上述等式即可。
+
+时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $value$ 的长度。
+
### **Python3**
@@ -40,7 +54,38 @@
```python
+class Solution:
+ def patternMatching(self, pattern: str, value: str) -> bool:
+ def check(la: int, lb: int) -> bool:
+ i = 0
+ a, b = "", ""
+ for c in pattern:
+ if c == "a":
+ if a and value[i : i + la] != a:
+ return False
+ a = value[i : i + la]
+ i += la
+ else:
+ if b and value[i : i + lb] != b:
+ return False
+ b = value[i : i + lb]
+ i += lb
+ return a != b
+ n = len(value)
+ cnt = Counter(pattern)
+ if cnt["a"] == 0:
+ return n % cnt["b"] == 0 and value[: n // cnt["b"]] * cnt["b"] == value
+ if cnt["b"] == 0:
+ return n % cnt["a"] == 0 and value[: n // cnt["a"]] * cnt["a"] == value
+
+ for la in range(n + 1):
+ if la * cnt["a"] > n:
+ break
+ lb, mod = divmod(n - la * cnt["a"], cnt["b"])
+ if mod == 0 and check(la, lb):
+ return True
+ return False
```
### **Java**
@@ -48,7 +93,219 @@
```java
+class Solution {
+ private String pattern;
+ private String value;
+
+ public boolean patternMatching(String pattern, String value) {
+ this.pattern = pattern;
+ this.value = value;
+ int[] cnt = new int[2];
+ for (char c : pattern.toCharArray()) {
+ ++cnt[c - 'a'];
+ }
+ int n = value.length();
+ if (cnt[0] == 0) {
+ return n % cnt[1] == 0 && value.substring(0, n / cnt[1]).repeat(cnt[1]).equals(value);
+ }
+ if (cnt[1] == 0) {
+ return n % cnt[0] == 0 && value.substring(0, n / cnt[0]).repeat(cnt[0]).equals(value);
+ }
+ for (int la = 0; la <= n; ++la) {
+ if (la * cnt[0] > n) {
+ break;
+ }
+ if ((n - la * cnt[0]) % cnt[1] == 0) {
+ int lb = (n - la * cnt[0]) / cnt[1];
+ if (check(la, lb)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean check(int la, int lb) {
+ int i = 0;
+ String a = null, b = null;
+ for (char c : pattern.toCharArray()) {
+ if (c == 'a') {
+ if (a != null && !a.equals(value.substring(i, i + la))) {
+ return false;
+ }
+ a = value.substring(i, i + la);
+ i += la;
+ } else {
+ if (b != null && !b.equals(value.substring(i, i + lb))) {
+ return false;
+ }
+ b = value.substring(i, i + lb);
+ i += lb;
+ }
+ }
+ return !a.equals(b);
+ }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+ bool patternMatching(string pattern, string value) {
+ int n = value.size();
+ int cnt[2]{};
+ for (char c : pattern) {
+ cnt[c - 'a']++;
+ }
+ if (cnt[0] == 0) {
+ return n % cnt[1] == 0 && repeat(value.substr(0, n / cnt[1]), cnt[1]) == value;
+ }
+ if (cnt[1] == 0) {
+ return n % cnt[0] == 0 && repeat(value.substr(0, n / cnt[0]), cnt[0]) == value;
+ }
+ auto check = [&](int la, int lb) {
+ int i = 0;
+ string a, b;
+ for (char c : pattern) {
+ if (c == 'a') {
+ if (!a.empty() && a != value.substr(i, la)) {
+ return false;
+ }
+ a = value.substr(i, la);
+ i += la;
+ } else {
+ if (!b.empty() && b != value.substr(i, lb)) {
+ return false;
+ }
+ b = value.substr(i, lb);
+ i += lb;
+ }
+ }
+ return a != b;
+ };
+ for (int la = 0; la <= n; ++la) {
+ if (la * cnt[0] > n) {
+ break;
+ }
+ if ((n - la * cnt[0]) % cnt[1] == 0) {
+ int lb = (n - la * cnt[0]) / cnt[1];
+ if (check(la, lb)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ string repeat(string s, int n) {
+ string ans;
+ while (n--) {
+ ans += s;
+ }
+ return ans;
+ }
+};
+```
+
+### **Go**
+
+```go
+func patternMatching(pattern string, value string) bool {
+ cnt := [2]int{}
+ for _, c := range pattern {
+ cnt[c-'a']++
+ }
+ n := len(value)
+ if cnt[0] == 0 {
+ return n%cnt[1] == 0 && strings.Repeat(value[:n/cnt[1]], cnt[1]) == value
+ }
+ if cnt[1] == 0 {
+ return n%cnt[0] == 0 && strings.Repeat(value[:n/cnt[0]], cnt[0]) == value
+ }
+ check := func(la, lb int) bool {
+ i := 0
+ a, b := "", ""
+ for _, c := range pattern {
+ if c == 'a' {
+ if a != "" && value[i:i+la] != a {
+ return false
+ }
+ a = value[i : i+la]
+ i += la
+ } else {
+ if b != "" && value[i:i+lb] != b {
+ return false
+ }
+ b = value[i : i+lb]
+ i += lb
+ }
+ }
+ return a != b
+ }
+ for la := 0; la <= n; la++ {
+ if la*cnt[0] > n {
+ break
+ }
+ if (n-la*cnt[0])%cnt[1] == 0 {
+ lb := (n - la*cnt[0]) / cnt[1]
+ if check(la, lb) {
+ return true
+ }
+ }
+ }
+ return false
+}
+```
+
+### **TypeScript**
+```ts
+function patternMatching(pattern: string, value: string): boolean {
+ const cnt: number[] = [0, 0];
+ for (const c of pattern) {
+ cnt[c === 'a' ? 0 : 1]++;
+ }
+ const n = value.length;
+ if (cnt[0] === 0) {
+ return n % cnt[1] === 0 && value.slice(0, (n / cnt[1]) | 0).repeat(cnt[1]) === value;
+ }
+ if (cnt[1] === 0) {
+ return n % cnt[0] === 0 && value.slice(0, (n / cnt[0]) | 0).repeat(cnt[0]) === value;
+ }
+ const check = (la: number, lb: number) => {
+ let i = 0;
+ let a = '';
+ let b = '';
+ for (const c of pattern) {
+ if (c === 'a') {
+ if (a && a !== value.slice(i, i + la)) {
+ return false;
+ }
+ a = value.slice(i, (i += la));
+ } else {
+ if (b && b !== value.slice(i, i + lb)) {
+ return false;
+ }
+ b = value.slice(i, (i += lb));
+ }
+ }
+ return a !== b;
+ };
+ for (let la = 0; la <= n; ++la) {
+ if (la * cnt[0] > n) {
+ break;
+ }
+ if ((n - la * cnt[0]) % cnt[1] === 0) {
+ const lb = ((n - la * cnt[0]) / cnt[1]) | 0;
+ if (check(la, lb)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
```
### **...**
diff --git a/lcci/16.18.Pattern Matching/README_EN.md b/lcci/16.18.Pattern Matching/README_EN.md
index e774841597a3e..14f6d86e948c5 100644
--- a/lcci/16.18.Pattern Matching/README_EN.md
+++ b/lcci/16.18.Pattern Matching/README_EN.md
@@ -53,13 +53,256 @@
### **Python3**
```python
+class Solution:
+ def patternMatching(self, pattern: str, value: str) -> bool:
+ def check(la: int, lb: int) -> bool:
+ i = 0
+ a, b = "", ""
+ for c in pattern:
+ if c == "a":
+ if a and value[i : i + la] != a:
+ return False
+ a = value[i : i + la]
+ i += la
+ else:
+ if b and value[i : i + lb] != b:
+ return False
+ b = value[i : i + lb]
+ i += lb
+ return a != b
+ n = len(value)
+ cnt = Counter(pattern)
+ if cnt["a"] == 0:
+ return n % cnt["b"] == 0 and value[: n // cnt["b"]] * cnt["b"] == value
+ if cnt["b"] == 0:
+ return n % cnt["a"] == 0 and value[: n // cnt["a"]] * cnt["a"] == value
+
+ for la in range(n + 1):
+ if la * cnt["a"] > n:
+ break
+ lb, mod = divmod(n - la * cnt["a"], cnt["b"])
+ if mod == 0 and check(la, lb):
+ return True
+ return False
```
### **Java**
```java
+class Solution {
+ private String pattern;
+ private String value;
+
+ public boolean patternMatching(String pattern, String value) {
+ this.pattern = pattern;
+ this.value = value;
+ int[] cnt = new int[2];
+ for (char c : pattern.toCharArray()) {
+ ++cnt[c - 'a'];
+ }
+ int n = value.length();
+ if (cnt[0] == 0) {
+ return n % cnt[1] == 0 && value.substring(0, n / cnt[1]).repeat(cnt[1]).equals(value);
+ }
+ if (cnt[1] == 0) {
+ return n % cnt[0] == 0 && value.substring(0, n / cnt[0]).repeat(cnt[0]).equals(value);
+ }
+ for (int la = 0; la <= n; ++la) {
+ if (la * cnt[0] > n) {
+ break;
+ }
+ if ((n - la * cnt[0]) % cnt[1] == 0) {
+ int lb = (n - la * cnt[0]) / cnt[1];
+ if (check(la, lb)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean check(int la, int lb) {
+ int i = 0;
+ String a = null, b = null;
+ for (char c : pattern.toCharArray()) {
+ if (c == 'a') {
+ if (a != null && !a.equals(value.substring(i, i + la))) {
+ return false;
+ }
+ a = value.substring(i, i + la);
+ i += la;
+ } else {
+ if (b != null && !b.equals(value.substring(i, i + lb))) {
+ return false;
+ }
+ b = value.substring(i, i + lb);
+ i += lb;
+ }
+ }
+ return !a.equals(b);
+ }
+}
+```
+
+### **C++**
+
+```cpp
+class Solution {
+public:
+ bool patternMatching(string pattern, string value) {
+ int n = value.size();
+ int cnt[2]{};
+ for (char c : pattern) {
+ cnt[c - 'a']++;
+ }
+ if (cnt[0] == 0) {
+ return n % cnt[1] == 0 && repeat(value.substr(0, n / cnt[1]), cnt[1]) == value;
+ }
+ if (cnt[1] == 0) {
+ return n % cnt[0] == 0 && repeat(value.substr(0, n / cnt[0]), cnt[0]) == value;
+ }
+ auto check = [&](int la, int lb) {
+ int i = 0;
+ string a, b;
+ for (char c : pattern) {
+ if (c == 'a') {
+ if (!a.empty() && a != value.substr(i, la)) {
+ return false;
+ }
+ a = value.substr(i, la);
+ i += la;
+ } else {
+ if (!b.empty() && b != value.substr(i, lb)) {
+ return false;
+ }
+ b = value.substr(i, lb);
+ i += lb;
+ }
+ }
+ return a != b;
+ };
+ for (int la = 0; la <= n; ++la) {
+ if (la * cnt[0] > n) {
+ break;
+ }
+ if ((n - la * cnt[0]) % cnt[1] == 0) {
+ int lb = (n - la * cnt[0]) / cnt[1];
+ if (check(la, lb)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ string repeat(string s, int n) {
+ string ans;
+ while (n--) {
+ ans += s;
+ }
+ return ans;
+ }
+};
+```
+
+### **Go**
+
+```go
+func patternMatching(pattern string, value string) bool {
+ cnt := [2]int{}
+ for _, c := range pattern {
+ cnt[c-'a']++
+ }
+ n := len(value)
+ if cnt[0] == 0 {
+ return n%cnt[1] == 0 && strings.Repeat(value[:n/cnt[1]], cnt[1]) == value
+ }
+ if cnt[1] == 0 {
+ return n%cnt[0] == 0 && strings.Repeat(value[:n/cnt[0]], cnt[0]) == value
+ }
+ check := func(la, lb int) bool {
+ i := 0
+ a, b := "", ""
+ for _, c := range pattern {
+ if c == 'a' {
+ if a != "" && value[i:i+la] != a {
+ return false
+ }
+ a = value[i : i+la]
+ i += la
+ } else {
+ if b != "" && value[i:i+lb] != b {
+ return false
+ }
+ b = value[i : i+lb]
+ i += lb
+ }
+ }
+ return a != b
+ }
+ for la := 0; la <= n; la++ {
+ if la*cnt[0] > n {
+ break
+ }
+ if (n-la*cnt[0])%cnt[1] == 0 {
+ lb := (n - la*cnt[0]) / cnt[1]
+ if check(la, lb) {
+ return true
+ }
+ }
+ }
+ return false
+}
+```
+
+### **TypeScript**
+```ts
+function patternMatching(pattern: string, value: string): boolean {
+ const cnt: number[] = [0, 0];
+ for (const c of pattern) {
+ cnt[c === 'a' ? 0 : 1]++;
+ }
+ const n = value.length;
+ if (cnt[0] === 0) {
+ return n % cnt[1] === 0 && value.slice(0, (n / cnt[1]) | 0).repeat(cnt[1]) === value;
+ }
+ if (cnt[1] === 0) {
+ return n % cnt[0] === 0 && value.slice(0, (n / cnt[0]) | 0).repeat(cnt[0]) === value;
+ }
+ const check = (la: number, lb: number) => {
+ let i = 0;
+ let a = '';
+ let b = '';
+ for (const c of pattern) {
+ if (c === 'a') {
+ if (a && a !== value.slice(i, i + la)) {
+ return false;
+ }
+ a = value.slice(i, (i += la));
+ } else {
+ if (b && b !== value.slice(i, i + lb)) {
+ return false;
+ }
+ b = value.slice(i, (i += lb));
+ }
+ }
+ return a !== b;
+ };
+ for (let la = 0; la <= n; ++la) {
+ if (la * cnt[0] > n) {
+ break;
+ }
+ if ((n - la * cnt[0]) % cnt[1] === 0) {
+ const lb = ((n - la * cnt[0]) / cnt[1]) | 0;
+ if (check(la, lb)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
```
### **...**
diff --git a/lcci/16.18.Pattern Matching/Solution.cpp b/lcci/16.18.Pattern Matching/Solution.cpp
new file mode 100644
index 0000000000000..8b3c00c642f9e
--- /dev/null
+++ b/lcci/16.18.Pattern Matching/Solution.cpp
@@ -0,0 +1,56 @@
+class Solution {
+public:
+ bool patternMatching(string pattern, string value) {
+ int n = value.size();
+ int cnt[2]{};
+ for (char c : pattern) {
+ cnt[c - 'a']++;
+ }
+ if (cnt[0] == 0) {
+ return n % cnt[1] == 0 && repeat(value.substr(0, n / cnt[1]), cnt[1]) == value;
+ }
+ if (cnt[1] == 0) {
+ return n % cnt[0] == 0 && repeat(value.substr(0, n / cnt[0]), cnt[0]) == value;
+ }
+ auto check = [&](int la, int lb) {
+ int i = 0;
+ string a, b;
+ for (char c : pattern) {
+ if (c == 'a') {
+ if (!a.empty() && a != value.substr(i, la)) {
+ return false;
+ }
+ a = value.substr(i, la);
+ i += la;
+ } else {
+ if (!b.empty() && b != value.substr(i, lb)) {
+ return false;
+ }
+ b = value.substr(i, lb);
+ i += lb;
+ }
+ }
+ return a != b;
+ };
+ for (int la = 0; la <= n; ++la) {
+ if (la * cnt[0] > n) {
+ break;
+ }
+ if ((n - la * cnt[0]) % cnt[1] == 0) {
+ int lb = (n - la * cnt[0]) / cnt[1];
+ if (check(la, lb)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ string repeat(string s, int n) {
+ string ans;
+ while (n--) {
+ ans += s;
+ }
+ return ans;
+ }
+};
\ No newline at end of file
diff --git a/lcci/16.18.Pattern Matching/Solution.go b/lcci/16.18.Pattern Matching/Solution.go
new file mode 100644
index 0000000000000..d457e8fe64fe2
--- /dev/null
+++ b/lcci/16.18.Pattern Matching/Solution.go
@@ -0,0 +1,45 @@
+func patternMatching(pattern string, value string) bool {
+ cnt := [2]int{}
+ for _, c := range pattern {
+ cnt[c-'a']++
+ }
+ n := len(value)
+ if cnt[0] == 0 {
+ return n%cnt[1] == 0 && strings.Repeat(value[:n/cnt[1]], cnt[1]) == value
+ }
+ if cnt[1] == 0 {
+ return n%cnt[0] == 0 && strings.Repeat(value[:n/cnt[0]], cnt[0]) == value
+ }
+ check := func(la, lb int) bool {
+ i := 0
+ a, b := "", ""
+ for _, c := range pattern {
+ if c == 'a' {
+ if a != "" && value[i:i+la] != a {
+ return false
+ }
+ a = value[i : i+la]
+ i += la
+ } else {
+ if b != "" && value[i:i+lb] != b {
+ return false
+ }
+ b = value[i : i+lb]
+ i += lb
+ }
+ }
+ return a != b
+ }
+ for la := 0; la <= n; la++ {
+ if la*cnt[0] > n {
+ break
+ }
+ if (n-la*cnt[0])%cnt[1] == 0 {
+ lb := (n - la*cnt[0]) / cnt[1]
+ if check(la, lb) {
+ return true
+ }
+ }
+ }
+ return false
+}
\ No newline at end of file
diff --git a/lcci/16.18.Pattern Matching/Solution.java b/lcci/16.18.Pattern Matching/Solution.java
new file mode 100644
index 0000000000000..0f6c1815e3ddb
--- /dev/null
+++ b/lcci/16.18.Pattern Matching/Solution.java
@@ -0,0 +1,53 @@
+class Solution {
+ private String pattern;
+ private String value;
+
+ public boolean patternMatching(String pattern, String value) {
+ this.pattern = pattern;
+ this.value = value;
+ int[] cnt = new int[2];
+ for (char c : pattern.toCharArray()) {
+ ++cnt[c - 'a'];
+ }
+ int n = value.length();
+ if (cnt[0] == 0) {
+ return n % cnt[1] == 0 && value.substring(0, n / cnt[1]).repeat(cnt[1]).equals(value);
+ }
+ if (cnt[1] == 0) {
+ return n % cnt[0] == 0 && value.substring(0, n / cnt[0]).repeat(cnt[0]).equals(value);
+ }
+ for (int la = 0; la <= n; ++la) {
+ if (la * cnt[0] > n) {
+ break;
+ }
+ if ((n - la * cnt[0]) % cnt[1] == 0) {
+ int lb = (n - la * cnt[0]) / cnt[1];
+ if (check(la, lb)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean check(int la, int lb) {
+ int i = 0;
+ String a = null, b = null;
+ for (char c : pattern.toCharArray()) {
+ if (c == 'a') {
+ if (a != null && !a.equals(value.substring(i, i + la))) {
+ return false;
+ }
+ a = value.substring(i, i + la);
+ i += la;
+ } else {
+ if (b != null && !b.equals(value.substring(i, i + lb))) {
+ return false;
+ }
+ b = value.substring(i, i + lb);
+ i += lb;
+ }
+ }
+ return !a.equals(b);
+ }
+}
\ No newline at end of file
diff --git a/lcci/16.18.Pattern Matching/Solution.py b/lcci/16.18.Pattern Matching/Solution.py
new file mode 100644
index 0000000000000..3d05b768dd19f
--- /dev/null
+++ b/lcci/16.18.Pattern Matching/Solution.py
@@ -0,0 +1,32 @@
+class Solution:
+ def patternMatching(self, pattern: str, value: str) -> bool:
+ def check(la: int, lb: int) -> bool:
+ i = 0
+ a, b = "", ""
+ for c in pattern:
+ if c == "a":
+ if a and value[i : i + la] != a:
+ return False
+ a = value[i : i + la]
+ i += la
+ else:
+ if b and value[i : i + lb] != b:
+ return False
+ b = value[i : i + lb]
+ i += lb
+ return a != b
+
+ n = len(value)
+ cnt = Counter(pattern)
+ if cnt["a"] == 0:
+ return n % cnt["b"] == 0 and value[: n // cnt["b"]] * cnt["b"] == value
+ if cnt["b"] == 0:
+ return n % cnt["a"] == 0 and value[: n // cnt["a"]] * cnt["a"] == value
+
+ for la in range(n + 1):
+ if la * cnt["a"] > n:
+ break
+ lb, mod = divmod(n - la * cnt["a"], cnt["b"])
+ if mod == 0 and check(la, lb):
+ return True
+ return False
diff --git a/lcci/16.18.Pattern Matching/Solution.ts b/lcci/16.18.Pattern Matching/Solution.ts
new file mode 100644
index 0000000000000..36d99f2c07849
--- /dev/null
+++ b/lcci/16.18.Pattern Matching/Solution.ts
@@ -0,0 +1,44 @@
+function patternMatching(pattern: string, value: string): boolean {
+ const cnt: number[] = [0, 0];
+ for (const c of pattern) {
+ cnt[c === 'a' ? 0 : 1]++;
+ }
+ const n = value.length;
+ if (cnt[0] === 0) {
+ return n % cnt[1] === 0 && value.slice(0, (n / cnt[1]) | 0).repeat(cnt[1]) === value;
+ }
+ if (cnt[1] === 0) {
+ return n % cnt[0] === 0 && value.slice(0, (n / cnt[0]) | 0).repeat(cnt[0]) === value;
+ }
+ const check = (la: number, lb: number) => {
+ let i = 0;
+ let a = '';
+ let b = '';
+ for (const c of pattern) {
+ if (c === 'a') {
+ if (a && a !== value.slice(i, i + la)) {
+ return false;
+ }
+ a = value.slice(i, (i += la));
+ } else {
+ if (b && b !== value.slice(i, i + lb)) {
+ return false;
+ }
+ b = value.slice(i, (i += lb));
+ }
+ }
+ return a !== b;
+ };
+ for (let la = 0; la <= n; ++la) {
+ if (la * cnt[0] > n) {
+ break;
+ }
+ if ((n - la * cnt[0]) % cnt[1] === 0) {
+ const lb = ((n - la * cnt[0]) / cnt[1]) | 0;
+ if (check(la, lb)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/solution/2600-2699/2603.Collect Coins in a Tree/README.md b/solution/2600-2699/2603.Collect Coins in a Tree/README.md
index 1e52ff1e4d896..241897dba4506 100644
--- a/solution/2600-2699/2603.Collect Coins in a Tree/README.md
+++ b/solution/2600-2699/2603.Collect Coins in a Tree/README.md
@@ -68,7 +68,7 @@
经过上述操作后,我们得到了一棵新的树,且树的叶子节点都是金币为 $1$ 的节点。
-然后,我们在删除剩下的两层叶子节点,最终得到的是一棵所有节点都需要被访问的节点,我们只需要统计其边数,乘上 $2$,即为答案。
+然后,我们再删除剩下的两层叶子节点,最终得到的是一棵所有节点都需要被访问的节点,我们只需要统计其边数,乘上 $2$,即为答案。
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为节点数。