Skip to content

Commit b6b5db0

Browse files
authored
feat: add solution to lc problem: No.3328 (#3656)
No.3328.Find Cities in Each State II
1 parent da2ffb8 commit b6b5db0

File tree

9 files changed

+429
-0
lines changed

9 files changed

+429
-0
lines changed

.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ node_modules/
2525
/solution/2200-2299/2253.Dynamic Unpivoting of a Table/Solution.sql
2626
/solution/3100-3199/3150.Invalid Tweets II/Solution.sql
2727
/solution/3100-3199/3198.Find Cities in Each State/Solution.sql
28+
/solution/3300-3399/3328.Find Cities in Each State II/Solution.sql
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
---
2+
comments: true
3+
difficulty: 中等
4+
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README.md
5+
tags:
6+
- 数据库
7+
---
8+
9+
<!-- problem:start -->
10+
11+
# [3328. Find Cities in Each State II 🔒](https://leetcode.cn/problems/find-cities-in-each-state-ii)
12+
13+
[English Version](/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README_EN.md)
14+
15+
## 题目描述
16+
17+
<!-- description:start -->
18+
19+
<p>Table: <code>cities</code></p>
20+
21+
<pre>
22+
+-------------+---------+
23+
| Column Name | Type |
24+
+-------------+---------+
25+
| state | varchar |
26+
| city | varchar |
27+
+-------------+---------+
28+
(state, city) is the combination of columns with unique values for this table.
29+
Each row of this table contains the state name and the city name within that state.
30+
</pre>
31+
32+
<p>Write a solution to find <strong>all the cities</strong> in <strong>each state</strong> and analyze them based on the following requirements:</p>
33+
34+
<ul>
35+
<li>Combine all cities into a <strong>comma-separated</strong> string for each state.</li>
36+
<li>Only include states that have <strong>at least</strong> <code>3</code> cities.</li>
37+
<li>Only include states where <strong>at least one city</strong> starts with the <strong>same letter as the state name</strong>.</li>
38+
</ul>
39+
40+
<p>Return <em>the result table ordered by</em> <em>the count of matching-letter cities in <strong>descending</strong> order</em>&nbsp;<em>and then by state name in <strong>ascending</strong> order</em>.</p>
41+
42+
<p>The result format is in the following example.</p>
43+
44+
<p>&nbsp;</p>
45+
<p><strong class="example">Example:</strong></p>
46+
47+
<div class="example-block">
48+
<p><strong>Input:</strong></p>
49+
50+
<p>cities table:</p>
51+
52+
<pre class="example-io">
53+
+--------------+---------------+
54+
| state | city |
55+
+--------------+---------------+
56+
| New York | New York City |
57+
| New York | Newark |
58+
| New York | Buffalo |
59+
| New York | Rochester |
60+
| California | San Francisco |
61+
| California | Sacramento |
62+
| California | San Diego |
63+
| California | Los Angeles |
64+
| Texas | Tyler |
65+
| Texas | Temple |
66+
| Texas | Taylor |
67+
| Texas | Dallas |
68+
| Pennsylvania | Philadelphia |
69+
| Pennsylvania | Pittsburgh |
70+
| Pennsylvania | Pottstown |
71+
+--------------+---------------+
72+
</pre>
73+
74+
<p><strong>Output:</strong></p>
75+
76+
<pre class="example-io">
77+
+-------------+-------------------------------------------+-----------------------+
78+
| state | cities | matching_letter_count |
79+
+-------------+-------------------------------------------+-----------------------+
80+
| Pennsylvania| Philadelphia, Pittsburgh, Pottstown | 3 |
81+
| Texas | Dallas, Taylor, Temple, Tyler | 2 |
82+
| New York | Buffalo, Newark, New York City, Rochester | 2 |
83+
+-------------+-------------------------------------------+-----------------------+
84+
</pre>
85+
86+
<p><strong>Explanation:</strong></p>
87+
88+
<ul>
89+
<li><strong>Pennsylvania</strong>:
90+
91+
<ul>
92+
<li>Has 3 cities (meets minimum requirement)</li>
93+
<li>All 3 cities start with &#39;P&#39; (same as state)</li>
94+
<li>matching_letter_count = 3</li>
95+
</ul>
96+
</li>
97+
<li><strong>Texas</strong>:
98+
<ul>
99+
<li>Has 4 cities (meets minimum requirement)</li>
100+
<li>2 cities (Temple, Tyler) start with &#39;T&#39; (same as state)</li>
101+
<li>matching_letter_count = 2</li>
102+
</ul>
103+
</li>
104+
<li><strong>New York</strong>:
105+
<ul>
106+
<li>Has 4 cities (meets minimum requirement)</li>
107+
<li>2 cities (Newark, New York City) start with &#39;N&#39; (same as state)</li>
108+
<li>matching_letter_count = 2</li>
109+
</ul>
110+
</li>
111+
<li><strong>California</strong> is not included in the output because:
112+
<ul>
113+
<li>Although it has 4 cities (meets minimum requirement)</li>
114+
<li>No cities start with &#39;C&#39; (doesn&#39;t meet the matching letter requirement)</li>
115+
</ul>
116+
</li>
117+
118+
</ul>
119+
120+
<p><strong>Note:</strong></p>
121+
122+
<ul>
123+
<li>Results are ordered by matching_letter_count in descending order</li>
124+
<li>When matching_letter_count is the same (Texas and New York both have 2), they are ordered by state name alphabetically</li>
125+
<li>Cities in each row are ordered alphabetically</li>
126+
</ul>
127+
</div>
128+
129+
<!-- description:end -->
130+
131+
## 解法
132+
133+
<!-- solution:start -->
134+
135+
### 方法一:分组聚合 + 过滤
136+
137+
我们可以将 `cities` 表按照 `state` 字段进行分组聚合,然后对每个分组进行过滤,筛选出满足条件的分组。
138+
139+
<!-- tabs:start -->
140+
141+
#### MySQL
142+
143+
```sql
144+
# Write your MySQL query statement below
145+
SELECT
146+
state,
147+
GROUP_CONCAT(city ORDER BY city SEPARATOR ', ') AS cities,
148+
COUNT(
149+
CASE
150+
WHEN LEFT(city, 1) = LEFT(state, 1) THEN 1
151+
END
152+
) AS matching_letter_count
153+
FROM cities
154+
GROUP BY 1
155+
HAVING COUNT(city) >= 3 AND matching_letter_count > 0
156+
ORDER BY 3 DESC, 1;
157+
```
158+
159+
#### Pandas
160+
161+
```python
162+
import pandas as pd
163+
164+
165+
def state_city_analysis(cities: pd.DataFrame) -> pd.DataFrame:
166+
cities["matching_letter"] = cities["city"].str[0] == cities["state"].str[0]
167+
168+
result = (
169+
cities.groupby("state")
170+
.agg(
171+
cities=("city", lambda x: ", ".join(sorted(x))),
172+
matching_letter_count=("matching_letter", "sum"),
173+
city_count=("city", "count"),
174+
)
175+
.reset_index()
176+
)
177+
178+
result = result[(result["city_count"] >= 3) & (result["matching_letter_count"] > 0)]
179+
180+
result = result.sort_values(
181+
by=["matching_letter_count", "state"], ascending=[False, True]
182+
)
183+
184+
result = result.drop(columns=["city_count"])
185+
186+
return result
187+
```
188+
189+
<!-- tabs:end -->
190+
191+
<!-- solution:end -->
192+
193+
<!-- problem:end -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
---
2+
comments: true
3+
difficulty: Medium
4+
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README_EN.md
5+
tags:
6+
- Database
7+
---
8+
9+
<!-- problem:start -->
10+
11+
# [3328. Find Cities in Each State II 🔒](https://leetcode.com/problems/find-cities-in-each-state-ii)
12+
13+
[中文文档](/solution/3300-3399/3328.Find%20Cities%20in%20Each%20State%20II/README.md)
14+
15+
## Description
16+
17+
<!-- description:start -->
18+
19+
<p>Table: <code>cities</code></p>
20+
21+
<pre>
22+
+-------------+---------+
23+
| Column Name | Type |
24+
+-------------+---------+
25+
| state | varchar |
26+
| city | varchar |
27+
+-------------+---------+
28+
(state, city) is the combination of columns with unique values for this table.
29+
Each row of this table contains the state name and the city name within that state.
30+
</pre>
31+
32+
<p>Write a solution to find <strong>all the cities</strong> in <strong>each state</strong> and analyze them based on the following requirements:</p>
33+
34+
<ul>
35+
<li>Combine all cities into a <strong>comma-separated</strong> string for each state.</li>
36+
<li>Only include states that have <strong>at least</strong> <code>3</code> cities.</li>
37+
<li>Only include states where <strong>at least one city</strong> starts with the <strong>same letter as the state name</strong>.</li>
38+
</ul>
39+
40+
<p>Return <em>the result table ordered by</em> <em>the count of matching-letter cities in <strong>descending</strong> order</em>&nbsp;<em>and then by state name in <strong>ascending</strong> order</em>.</p>
41+
42+
<p>The result format is in the following example.</p>
43+
44+
<p>&nbsp;</p>
45+
<p><strong class="example">Example:</strong></p>
46+
47+
<div class="example-block">
48+
<p><strong>Input:</strong></p>
49+
50+
<p>cities table:</p>
51+
52+
<pre class="example-io">
53+
+--------------+---------------+
54+
| state | city |
55+
+--------------+---------------+
56+
| New York | New York City |
57+
| New York | Newark |
58+
| New York | Buffalo |
59+
| New York | Rochester |
60+
| California | San Francisco |
61+
| California | Sacramento |
62+
| California | San Diego |
63+
| California | Los Angeles |
64+
| Texas | Tyler |
65+
| Texas | Temple |
66+
| Texas | Taylor |
67+
| Texas | Dallas |
68+
| Pennsylvania | Philadelphia |
69+
| Pennsylvania | Pittsburgh |
70+
| Pennsylvania | Pottstown |
71+
+--------------+---------------+
72+
</pre>
73+
74+
<p><strong>Output:</strong></p>
75+
76+
<pre class="example-io">
77+
+-------------+-------------------------------------------+-----------------------+
78+
| state | cities | matching_letter_count |
79+
+-------------+-------------------------------------------+-----------------------+
80+
| Pennsylvania| Philadelphia, Pittsburgh, Pottstown | 3 |
81+
| Texas | Dallas, Taylor, Temple, Tyler | 2 |
82+
| New York | Buffalo, Newark, New York City, Rochester | 2 |
83+
+-------------+-------------------------------------------+-----------------------+
84+
</pre>
85+
86+
<p><strong>Explanation:</strong></p>
87+
88+
<ul>
89+
<li><strong>Pennsylvania</strong>:
90+
91+
<ul>
92+
<li>Has 3 cities (meets minimum requirement)</li>
93+
<li>All 3 cities start with &#39;P&#39; (same as state)</li>
94+
<li>matching_letter_count = 3</li>
95+
</ul>
96+
</li>
97+
<li><strong>Texas</strong>:
98+
<ul>
99+
<li>Has 4 cities (meets minimum requirement)</li>
100+
<li>2 cities (Temple, Tyler) start with &#39;T&#39; (same as state)</li>
101+
<li>matching_letter_count = 2</li>
102+
</ul>
103+
</li>
104+
<li><strong>New York</strong>:
105+
<ul>
106+
<li>Has 4 cities (meets minimum requirement)</li>
107+
<li>2 cities (Newark, New York City) start with &#39;N&#39; (same as state)</li>
108+
<li>matching_letter_count = 2</li>
109+
</ul>
110+
</li>
111+
<li><strong>California</strong> is not included in the output because:
112+
<ul>
113+
<li>Although it has 4 cities (meets minimum requirement)</li>
114+
<li>No cities start with &#39;C&#39; (doesn&#39;t meet the matching letter requirement)</li>
115+
</ul>
116+
</li>
117+
118+
</ul>
119+
120+
<p><strong>Note:</strong></p>
121+
122+
<ul>
123+
<li>Results are ordered by matching_letter_count in descending order</li>
124+
<li>When matching_letter_count is the same (Texas and New York both have 2), they are ordered by state name alphabetically</li>
125+
<li>Cities in each row are ordered alphabetically</li>
126+
</ul>
127+
</div>
128+
129+
<!-- description:end -->
130+
131+
## Solutions
132+
133+
<!-- solution:start -->
134+
135+
### Solution 1: Group Aggregation + Filtering
136+
137+
We can group the `cities` table by the `state` field, then apply filtering on each group to retain only the groups that meet the specified conditions.
138+
139+
<!-- tabs:start -->
140+
141+
#### MySQL
142+
143+
```sql
144+
# Write your MySQL query statement below
145+
SELECT
146+
state,
147+
GROUP_CONCAT(city ORDER BY city SEPARATOR ', ') AS cities,
148+
COUNT(
149+
CASE
150+
WHEN LEFT(city, 1) = LEFT(state, 1) THEN 1
151+
END
152+
) AS matching_letter_count
153+
FROM cities
154+
GROUP BY 1
155+
HAVING COUNT(city) >= 3 AND matching_letter_count > 0
156+
ORDER BY 3 DESC, 1;
157+
```
158+
159+
#### Pandas
160+
161+
```python
162+
import pandas as pd
163+
164+
165+
def state_city_analysis(cities: pd.DataFrame) -> pd.DataFrame:
166+
cities["matching_letter"] = cities["city"].str[0] == cities["state"].str[0]
167+
168+
result = (
169+
cities.groupby("state")
170+
.agg(
171+
cities=("city", lambda x: ", ".join(sorted(x))),
172+
matching_letter_count=("matching_letter", "sum"),
173+
city_count=("city", "count"),
174+
)
175+
.reset_index()
176+
)
177+
178+
result = result[(result["city_count"] >= 3) & (result["matching_letter_count"] > 0)]
179+
180+
result = result.sort_values(
181+
by=["matching_letter_count", "state"], ascending=[False, True]
182+
)
183+
184+
result = result.drop(columns=["city_count"])
185+
186+
return result
187+
```
188+
189+
<!-- tabs:end -->
190+
191+
<!-- solution:end -->
192+
193+
<!-- problem:end -->

0 commit comments

Comments
 (0)