Skip to content

Commit 22009c6

Browse files
committed
feat: add solutions to lc problem: No.1657
No.1657.Determine if Two Strings Are Close
1 parent d86e6f9 commit 22009c6

File tree

6 files changed

+269
-6
lines changed

6 files changed

+269
-6
lines changed

solution/1600-1699/1657.Determine if Two Strings Are Close/README.md

Lines changed: 102 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
<ul>
1212
<li>操作 1:交换任意两个 <strong>现有</strong> 字符。
13-
1413
<ul>
1514
<li>例如,<code>a<strong>b</strong>cd<strong>e</strong> -> a<strong>e</strong>cd<strong>b</strong></code></li>
1615
</ul>
@@ -20,7 +19,6 @@
2019
<li>例如,<code><strong>aa</strong>c<strong>abb</strong> -> <strong>bb</strong>c<strong>baa</strong></code>(所有 <code>a</code> 转化为 <code>b</code> ,而所有的 <code>b</code> 转换为 <code>a</code> )</li>
2120
</ul>
2221
</li>
23-
2422
</ul>
2523

2624
<p>你可以根据需要对任意一个字符串多次使用这两种操作。</p>
@@ -77,22 +75,123 @@
7775

7876
<!-- 这里可写通用的实现逻辑 -->
7977

78+
**方法一:数组或哈希表 + 排序**
79+
80+
根据题目描述,两个字符串接近,需要同时满足以下两个条件:
81+
82+
1. 字符串 `word1``word2` 包含的字母种类必须相同;
83+
1. 将字符串 `word1``word2` 的所有字符出现次数排序,得到的两个数组必须相同。
84+
85+
因此,我们可以先用数组或哈希表分别统计 `word1``word2` 中每种字母出现的次数,然后比较两者是否相同,不相同则提前返回 `false`
86+
87+
否则,我们将对应的次数排序,然后依次比较对应位置的两个次数是否相同,不同则返回 `false`
88+
89+
遍历结束,返回 `true`
90+
91+
时间复杂度 $O(m + n)$,空间复杂度 $O(C)$。其中 $m$ 和 $n$ 分别为字符串 `word1``word2` 的长度,而 $C$ 是字母种类。本题中 $C=26$。
92+
8093
<!-- tabs:start -->
8194

8295
### **Python3**
8396

8497
<!-- 这里可写当前语言的特殊实现逻辑 -->
8598

8699
```python
87-
100+
class Solution:
101+
def closeStrings(self, word1: str, word2: str) -> bool:
102+
cnt1, cnt2 = Counter(word1), Counter(word2)
103+
return sorted(cnt1.values()) == sorted(cnt2.values()) and set(cnt1.keys()) == set(cnt2.keys())
88104
```
89105

90106
### **Java**
91107

92108
<!-- 这里可写当前语言的特殊实现逻辑 -->
93109

94110
```java
111+
class Solution {
112+
public boolean closeStrings(String word1, String word2) {
113+
int[] cnt1 = new int[26];
114+
int[] cnt2 = new int[26];
115+
for (int i = 0; i < word1.length(); ++i) {
116+
++cnt1[word1.charAt(i) - 'a'];
117+
}
118+
for (int i = 0; i < word2.length(); ++i) {
119+
++cnt2[word2.charAt(i) - 'a'];
120+
}
121+
for (int i = 0; i < 26; ++i) {
122+
if ((cnt1[i] > 0 && cnt2[i] == 0) || (cnt2[i] > 0 && cnt1[i] == 0)) {
123+
return false;
124+
}
125+
}
126+
Arrays.sort(cnt1);
127+
Arrays.sort(cnt2);
128+
for (int i = 0; i < 26; ++i) {
129+
if (cnt1[i] != cnt2[i]) {
130+
return false;
131+
}
132+
}
133+
return true;
134+
}
135+
}
136+
```
137+
138+
### **C++**
139+
140+
```cpp
141+
class Solution {
142+
public:
143+
bool closeStrings(string word1, string word2) {
144+
int cnt1[26]{};
145+
int cnt2[26]{};
146+
for (char& c : word1) {
147+
++cnt1[c - 'a'];
148+
}
149+
for (char& c : word2) {
150+
++cnt2[c - 'a'];
151+
}
152+
for (int i = 0; i < 26; ++i) {
153+
if ((cnt1[i] > 0 && cnt2[i] == 0) || (cnt1[i] == 0 && cnt2[i] > 0)) {
154+
return false;
155+
}
156+
}
157+
sort(cnt1, cnt1 + 26);
158+
sort(cnt2, cnt2 + 26);
159+
for (int i = 0; i < 26; ++i) {
160+
if (cnt1[i] != cnt2[i]) {
161+
return false;
162+
}
163+
}
164+
return true;
165+
}
166+
};
167+
```
95168
169+
### **Go**
170+
171+
```go
172+
func closeStrings(word1 string, word2 string) bool {
173+
cnt1 := make([]int, 26)
174+
cnt2 := make([]int, 26)
175+
for _, c := range word1 {
176+
cnt1[c-'a']++
177+
}
178+
for _, c := range word2 {
179+
cnt2[c-'a']++
180+
}
181+
for i, v := range cnt1 {
182+
if (v > 0 && cnt2[i] == 0) || (v == 0 && cnt2[i] > 0) {
183+
return false
184+
}
185+
}
186+
sort.Ints(cnt1)
187+
sort.Ints(cnt2)
188+
for i, v := range cnt1 {
189+
if v != cnt2[i] {
190+
return false
191+
}
192+
}
193+
return true
194+
}
96195
```
97196

98197
### **...**

solution/1600-1699/1657.Determine if Two Strings Are Close/README_EN.md

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
<ul>
1010
<li>Operation 1: Swap any two <strong>existing</strong> characters.
11-
1211
<ul>
1312
<li>For example, <code>a<u>b</u>cd<u>e</u> -&gt; a<u>e</u>cd<u>b</u></code></li>
1413
</ul>
@@ -18,7 +17,6 @@
1817
<li>For example, <code><u>aa</u>c<u>abb</u> -&gt; <u>bb</u>c<u>baa</u></code> (all <code>a</code>&#39;s turn into <code>b</code>&#39;s, and all <code>b</code>&#39;s turn into <code>a</code>&#39;s)</li>
1918
</ul>
2019
</li>
21-
2220
</ul>
2321

2422
<p>You can use the operations on either string as many times as necessary.</p>
@@ -70,13 +68,99 @@ Apply Operation 2: &quot;<u>baa</u>ccc&quot; -&gt; &quot;<u>abb</u>ccc&quot;
7068
### **Python3**
7169

7270
```python
73-
71+
class Solution:
72+
def closeStrings(self, word1: str, word2: str) -> bool:
73+
cnt1, cnt2 = Counter(word1), Counter(word2)
74+
return sorted(cnt1.values()) == sorted(cnt2.values()) and set(cnt1.keys()) == set(cnt2.keys())
7475
```
7576

7677
### **Java**
7778

7879
```java
80+
class Solution {
81+
public boolean closeStrings(String word1, String word2) {
82+
int[] cnt1 = new int[26];
83+
int[] cnt2 = new int[26];
84+
for (int i = 0; i < word1.length(); ++i) {
85+
++cnt1[word1.charAt(i) - 'a'];
86+
}
87+
for (int i = 0; i < word2.length(); ++i) {
88+
++cnt2[word2.charAt(i) - 'a'];
89+
}
90+
for (int i = 0; i < 26; ++i) {
91+
if ((cnt1[i] > 0 && cnt2[i] == 0) || (cnt2[i] > 0 && cnt1[i] == 0)) {
92+
return false;
93+
}
94+
}
95+
Arrays.sort(cnt1);
96+
Arrays.sort(cnt2);
97+
for (int i = 0; i < 26; ++i) {
98+
if (cnt1[i] != cnt2[i]) {
99+
return false;
100+
}
101+
}
102+
return true;
103+
}
104+
}
105+
```
106+
107+
### **C++**
108+
109+
```cpp
110+
class Solution {
111+
public:
112+
bool closeStrings(string word1, string word2) {
113+
int cnt1[26]{};
114+
int cnt2[26]{};
115+
for (char& c : word1) {
116+
++cnt1[c - 'a'];
117+
}
118+
for (char& c : word2) {
119+
++cnt2[c - 'a'];
120+
}
121+
for (int i = 0; i < 26; ++i) {
122+
if ((cnt1[i] > 0 && cnt2[i] == 0) || (cnt1[i] == 0 && cnt2[i] > 0)) {
123+
return false;
124+
}
125+
}
126+
sort(cnt1, cnt1 + 26);
127+
sort(cnt2, cnt2 + 26);
128+
for (int i = 0; i < 26; ++i) {
129+
if (cnt1[i] != cnt2[i]) {
130+
return false;
131+
}
132+
}
133+
return true;
134+
}
135+
};
136+
```
79137
138+
### **Go**
139+
140+
```go
141+
func closeStrings(word1 string, word2 string) bool {
142+
cnt1 := make([]int, 26)
143+
cnt2 := make([]int, 26)
144+
for _, c := range word1 {
145+
cnt1[c-'a']++
146+
}
147+
for _, c := range word2 {
148+
cnt2[c-'a']++
149+
}
150+
for i, v := range cnt1 {
151+
if (v > 0 && cnt2[i] == 0) || (v == 0 && cnt2[i] > 0) {
152+
return false
153+
}
154+
}
155+
sort.Ints(cnt1)
156+
sort.Ints(cnt2)
157+
for i, v := range cnt1 {
158+
if v != cnt2[i] {
159+
return false
160+
}
161+
}
162+
return true
163+
}
80164
```
81165

82166
### **...**
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class Solution {
2+
public:
3+
bool closeStrings(string word1, string word2) {
4+
int cnt1[26]{};
5+
int cnt2[26]{};
6+
for (char& c : word1) {
7+
++cnt1[c - 'a'];
8+
}
9+
for (char& c : word2) {
10+
++cnt2[c - 'a'];
11+
}
12+
for (int i = 0; i < 26; ++i) {
13+
if ((cnt1[i] > 0 && cnt2[i] == 0) || (cnt1[i] == 0 && cnt2[i] > 0)) {
14+
return false;
15+
}
16+
}
17+
sort(cnt1, cnt1 + 26);
18+
sort(cnt2, cnt2 + 26);
19+
for (int i = 0; i < 26; ++i) {
20+
if (cnt1[i] != cnt2[i]) {
21+
return false;
22+
}
23+
}
24+
return true;
25+
}
26+
};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
func closeStrings(word1 string, word2 string) bool {
2+
cnt1 := make([]int, 26)
3+
cnt2 := make([]int, 26)
4+
for _, c := range word1 {
5+
cnt1[c-'a']++
6+
}
7+
for _, c := range word2 {
8+
cnt2[c-'a']++
9+
}
10+
for i, v := range cnt1 {
11+
if (v > 0 && cnt2[i] == 0) || (v == 0 && cnt2[i] > 0) {
12+
return false
13+
}
14+
}
15+
sort.Ints(cnt1)
16+
sort.Ints(cnt2)
17+
for i, v := range cnt1 {
18+
if v != cnt2[i] {
19+
return false
20+
}
21+
}
22+
return true
23+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
class Solution {
2+
public boolean closeStrings(String word1, String word2) {
3+
int[] cnt1 = new int[26];
4+
int[] cnt2 = new int[26];
5+
for (int i = 0; i < word1.length(); ++i) {
6+
++cnt1[word1.charAt(i) - 'a'];
7+
}
8+
for (int i = 0; i < word2.length(); ++i) {
9+
++cnt2[word2.charAt(i) - 'a'];
10+
}
11+
for (int i = 0; i < 26; ++i) {
12+
if ((cnt1[i] > 0 && cnt2[i] == 0) || (cnt2[i] > 0 && cnt1[i] == 0)) {
13+
return false;
14+
}
15+
}
16+
Arrays.sort(cnt1);
17+
Arrays.sort(cnt2);
18+
for (int i = 0; i < 26; ++i) {
19+
if (cnt1[i] != cnt2[i]) {
20+
return false;
21+
}
22+
}
23+
return true;
24+
}
25+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Solution:
2+
def closeStrings(self, word1: str, word2: str) -> bool:
3+
cnt1, cnt2 = Counter(word1), Counter(word2)
4+
return sorted(cnt1.values()) == sorted(cnt2.values()) and set(
5+
cnt1.keys()
6+
) == set(cnt2.keys())

0 commit comments

Comments
 (0)