Skip to content

Commit cd0409a

Browse files
authored
feat: add solutions to lc problem: No.3421 (doocs#3951)
No.3421.Find Students Who Improved
1 parent 6a244ec commit cd0409a

File tree

8 files changed

+340
-2
lines changed

8 files changed

+340
-2
lines changed

solution/0500-0599/0563.Binary Tree Tilt/README_EN.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ tags:
2828
<pre>
2929
<strong>Input:</strong> root = [1,2,3]
3030
<strong>Output:</strong> 1
31-
<strong>Explanation:</strong>
31+
<strong>Explanation:</strong>
3232
Tilt of node 2 : |0-0| = 0 (no children)
3333
Tilt of node 3 : |0-0| = 0 (no children)
3434
Tilt of node 1 : |2-3| = 1 (left subtree is just left child, so sum is 2; right subtree is just right child, so sum is 3)
@@ -40,7 +40,7 @@ Sum of every tilt : 0 + 0 + 1 = 1
4040
<pre>
4141
<strong>Input:</strong> root = [4,2,9,3,5,null,7]
4242
<strong>Output:</strong> 15
43-
<strong>Explanation:</strong>
43+
<strong>Explanation:</strong>
4444
Tilt of node 3 : |0-0| = 0 (no children)
4545
Tilt of node 5 : |0-0| = 0 (no children)
4646
Tilt of node 7 : |0-0| = 0 (no children)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
---
2+
comments: true
3+
difficulty: 中等
4+
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README.md
5+
tags:
6+
- 数据库
7+
---
8+
9+
<!-- problem:start -->
10+
11+
# [3421. 查找进步的学生](https://leetcode.cn/problems/find-students-who-improved)
12+
13+
[English Version](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README_EN.md)
14+
15+
## 题目描述
16+
17+
<!-- description:start -->
18+
19+
<p>表:<code>Scores</code></p>
20+
21+
<pre>
22+
+-------------+---------+
23+
| Column Name | Type |
24+
+-------------+---------+
25+
| student_id | int |
26+
| subject | varchar |
27+
| score | int |
28+
| exam_date | varchar |
29+
+-------------+---------+
30+
(student_id, subject, exam_date) 是这张表的主键。
31+
每一行包含有关学生在特定考试日期特定科目成绩的信息。分数范围从 0 到 100(包括边界)。
32+
</pre>
33+
34+
<p>编写一个解决方案来查找 <strong>进步的学生</strong>。如果 <strong>同时</strong> 满足以下两个条件,则该学生被认为是进步的:</p>
35+
36+
<ul>
37+
<li>在 <strong>同一科目</strong>&nbsp;至少有两个不同日期的考试。</li>
38+
<li>他们在该学科&nbsp;<strong>最近的分数</strong>&nbsp;比他们 <strong>第一次的分数更高。</strong></li>
39+
</ul>
40+
41+
<p>返回结果表以&nbsp;<code>student_id</code>,<code>subject</code> <strong>升序</strong>&nbsp;排序。</p>
42+
43+
<p>结果格式如下所示。</p>
44+
45+
<p>&nbsp;</p>
46+
47+
<p><strong class="example">示例:</strong></p>
48+
49+
<div class="example-block">
50+
<p><strong>输入:</strong></p>
51+
52+
<p>Scores 表:</p>
53+
54+
<pre class="example-io">
55+
+------------+----------+-------+------------+
56+
| student_id | subject | score | exam_date |
57+
+------------+----------+-------+------------+
58+
| 101 | Math | 70 | 15-01-2023 |
59+
| 101 | Math | 85 | 15-02-2023 |
60+
| 101 | Physics | 65 | 15-01-2023 |
61+
| 101 | Physics | 60 | 15-02-2023 |
62+
| 102 | Math | 80 | 15-01-2023 |
63+
| 102 | Math | 85 | 15-02-2023 |
64+
| 103 | Math | 90 | 15-01-2023 |
65+
| 104 | Physics | 75 | 15-01-2023 |
66+
| 104 | Physics | 85 | 15-02-2023 |
67+
+------------+----------+-------+------------+
68+
</pre>
69+
70+
<p><strong>输出:</strong></p>
71+
72+
<pre class="example-io">
73+
+------------+----------+-------------+--------------+
74+
| student_id | subject | first_score | latest_score |
75+
+------------+----------+-------------+--------------+
76+
| 101 | Math | 70 | 85 |
77+
| 102 | Math | 80 | 85 |
78+
| 104 | Physics | 75 | 85 |
79+
+------------+----------+-------------+--------------+
80+
</pre>
81+
82+
<p><strong>解释:</strong></p>
83+
84+
<ul>
85+
<li>学生 101 的数学:从 70 分进步到 85 分。</li>
86+
<li>学生 101 的物理:没有进步(从 65 分退步到 60分)</li>
87+
<li>学生 102 的数学:从 80 进步到 85 分。</li>
88+
<li>学生 103 的数学:只有一次考试,不符合资格。</li>
89+
<li>学生 104 in Physics:从 75 分进步到 85 分。</li>
90+
</ul>
91+
92+
<p>结果表以 student_id,subject 升序排序。</p>
93+
</div>
94+
95+
<!-- description:end -->
96+
97+
## 解法
98+
99+
<!-- solution:start -->
100+
101+
### 方法一:窗口函数 + 子连接 + 条件过滤
102+
103+
首先,我们使用窗口函数 `ROW_NUMBER()` 计算每个学生在每个科目中的考试日期的排名,分别计算出每个学生在每个科目中的第一次考试和最近一次考试的排名。
104+
105+
然后,我们使用子连接 `JOIN` 操作将第一次考试和最近一次考试的分数连接在一起,最后根据题目要求筛选出最近一次考试的分数比第一次考试的分数高的学生。
106+
107+
<!-- tabs:start -->
108+
109+
#### MySQL
110+
111+
```sql
112+
WITH
113+
RankedScores AS (
114+
SELECT
115+
student_id,
116+
subject,
117+
score,
118+
exam_date,
119+
ROW_NUMBER() OVER (
120+
PARTITION BY student_id, subject
121+
ORDER BY exam_date ASC
122+
) AS rn_first,
123+
ROW_NUMBER() OVER (
124+
PARTITION BY student_id, subject
125+
ORDER BY exam_date DESC
126+
) AS rn_latest
127+
FROM Scores
128+
),
129+
FirstAndLatestScores AS (
130+
SELECT
131+
f.student_id,
132+
f.subject,
133+
f.score AS first_score,
134+
l.score AS latest_score
135+
FROM
136+
RankedScores f
137+
JOIN RankedScores l ON f.student_id = l.student_id AND f.subject = l.subject
138+
WHERE f.rn_first = 1 AND l.rn_latest = 1
139+
)
140+
SELECT
141+
*
142+
FROM FirstAndLatestScores
143+
WHERE latest_score > first_score
144+
ORDER BY 1, 2;
145+
```
146+
147+
<!-- tabs:end -->
148+
149+
<!-- solution:end -->
150+
151+
<!-- problem:end -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
---
2+
comments: true
3+
difficulty: Medium
4+
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README_EN.md
5+
tags:
6+
- Database
7+
---
8+
9+
<!-- problem:start -->
10+
11+
# [3421. Find Students Who Improved](https://leetcode.com/problems/find-students-who-improved)
12+
13+
[中文文档](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README.md)
14+
15+
## Description
16+
17+
<!-- description:start -->
18+
19+
<p>Table: <code>Scores</code></p>
20+
21+
<pre>
22+
+-------------+---------+
23+
| Column Name | Type |
24+
+-------------+---------+
25+
| student_id | int |
26+
| subject | varchar |
27+
| score | int |
28+
| exam_date | varchar |
29+
+-------------+---------+
30+
(student_id, subject, exam_date) is the primary key for this table.
31+
Each row contains information about a student&#39;s score in a specific subject on a particular exam date. score is between 0 and 100 (inclusive).
32+
</pre>
33+
34+
<p>Write a solution to find the <strong>students who have shown improvement</strong>. A student is considered to have shown improvement if they meet <strong>both</strong> of these conditions:</p>
35+
36+
<ul>
37+
<li>Have taken exams in the <strong>same subject</strong> on at least two different dates</li>
38+
<li>Their <strong>latest score</strong> in that subject is <strong>higher</strong> than their <strong>first score</strong></li>
39+
</ul>
40+
41+
<p>Return <em>the result table</em>&nbsp;<em>ordered by</em> <code>student_id,</code> <code>subject</code> <em>in <strong>ascending</strong> order</em>.</p>
42+
43+
<p>The result format is in the following example.</p>
44+
45+
<p>&nbsp;</p>
46+
<p><strong class="example">Example:</strong></p>
47+
48+
<div class="example-block">
49+
<p><strong>Input:</strong></p>
50+
51+
<p>Scores table:</p>
52+
53+
<pre class="example-io">
54+
+------------+----------+-------+------------+
55+
| student_id | subject | score | exam_date |
56+
+------------+----------+-------+------------+
57+
| 101 | Math | 70 | 15-01-2023 |
58+
| 101 | Math | 85 | 15-02-2023 |
59+
| 101 | Physics | 65 | 15-01-2023 |
60+
| 101 | Physics | 60 | 15-02-2023 |
61+
| 102 | Math | 80 | 15-01-2023 |
62+
| 102 | Math | 85 | 15-02-2023 |
63+
| 103 | Math | 90 | 15-01-2023 |
64+
| 104 | Physics | 75 | 15-01-2023 |
65+
| 104 | Physics | 85 | 15-02-2023 |
66+
+------------+----------+-------+------------+
67+
</pre>
68+
69+
<p><strong>Output:</strong></p>
70+
71+
<pre class="example-io">
72+
+------------+----------+-------------+--------------+
73+
| student_id | subject | first_score | latest_score |
74+
+------------+----------+-------------+--------------+
75+
| 101 | Math | 70 | 85 |
76+
| 102 | Math | 80 | 85 |
77+
| 104 | Physics | 75 | 85 |
78+
+------------+----------+-------------+--------------+
79+
</pre>
80+
81+
<p><strong>Explanation:</strong></p>
82+
83+
<ul>
84+
<li>Student 101 in Math: Improved from 70 to 85</li>
85+
<li>Student 101 in Physics: No improvement (dropped from 65 to 60)</li>
86+
<li>Student 102 in Math: Improved from 80 to 85</li>
87+
<li>Student 103 in Math: Only one exam, not eligible</li>
88+
<li>Student 104 in Physics: Improved from 75 to 85</li>
89+
</ul>
90+
91+
<p>Result table is ordered by student_id, subject.</p>
92+
</div>
93+
94+
<!-- description:end -->
95+
96+
## Solutions
97+
98+
<!-- solution:start -->
99+
100+
### Solution 1: Window Function + Subquery + Conditional Filtering
101+
102+
First, we use the window function `ROW_NUMBER()` to calculate the ranking of each student's exam date in each subject, separately calculating the first and most recent exam rankings for each student in each subject.
103+
104+
Then, we use a subquery `JOIN` operation to join the scores of the first and most recent exams together. Finally, we filter out the students whose most recent exam scores are higher than their first exam scores according to the problem requirements.
105+
106+
<!-- tabs:start -->
107+
108+
#### MySQL
109+
110+
```sql
111+
WITH
112+
RankedScores AS (
113+
SELECT
114+
student_id,
115+
subject,
116+
score,
117+
exam_date,
118+
ROW_NUMBER() OVER (
119+
PARTITION BY student_id, subject
120+
ORDER BY exam_date ASC
121+
) AS rn_first,
122+
ROW_NUMBER() OVER (
123+
PARTITION BY student_id, subject
124+
ORDER BY exam_date DESC
125+
) AS rn_latest
126+
FROM Scores
127+
),
128+
FirstAndLatestScores AS (
129+
SELECT
130+
f.student_id,
131+
f.subject,
132+
f.score AS first_score,
133+
l.score AS latest_score
134+
FROM
135+
RankedScores f
136+
JOIN RankedScores l ON f.student_id = l.student_id AND f.subject = l.subject
137+
WHERE f.rn_first = 1 AND l.rn_latest = 1
138+
)
139+
SELECT
140+
*
141+
FROM FirstAndLatestScores
142+
WHERE latest_score > first_score
143+
ORDER BY 1, 2;
144+
```
145+
146+
<!-- tabs:end -->
147+
148+
<!-- solution:end -->
149+
150+
<!-- problem:end -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
WITH
2+
RankedScores AS (
3+
SELECT
4+
student_id,
5+
subject,
6+
score,
7+
exam_date,
8+
ROW_NUMBER() OVER (
9+
PARTITION BY student_id, subject
10+
ORDER BY exam_date ASC
11+
) AS rn_first,
12+
ROW_NUMBER() OVER (
13+
PARTITION BY student_id, subject
14+
ORDER BY exam_date DESC
15+
) AS rn_latest
16+
FROM Scores
17+
),
18+
FirstAndLatestScores AS (
19+
SELECT
20+
f.student_id,
21+
f.subject,
22+
f.score AS first_score,
23+
l.score AS latest_score
24+
FROM
25+
RankedScores f
26+
JOIN RankedScores l ON f.student_id = l.student_id AND f.subject = l.subject
27+
WHERE f.rn_first = 1 AND l.rn_latest = 1
28+
)
29+
SELECT
30+
*
31+
FROM FirstAndLatestScores
32+
WHERE latest_score > first_score
33+
ORDER BY 1, 2;

solution/DATABASE_README.md

+1
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@
307307
| 3390 | [Longest Team Pass Streak](/solution/3300-3399/3390.Longest%20Team%20Pass%20Streak/README.md) | `数据库` | 困难 | 🔒 |
308308
| 3401 | [Find Circular Gift Exchange Chains](/solution/3400-3499/3401.Find%20Circular%20Gift%20Exchange%20Chains/README.md) | `数据库` | 困难 | 🔒 |
309309
| 3415 | [查找具有三个连续数字的产品](/solution/3400-3499/3415.Find%20Products%20with%20Three%20Consecutive%20Digits/README.md) | `数据库` | 简单 | 🔒 |
310+
| 3421 | [查找进步的学生](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README.md) | | 中等 | |
310311

311312
## 版权
312313

solution/DATABASE_README_EN.md

+1
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ Press <kbd>Control</kbd> + <kbd>F</kbd>(or <kbd>Command</kbd> + <kbd>F</kbd> on
305305
| 3390 | [Longest Team Pass Streak](/solution/3300-3399/3390.Longest%20Team%20Pass%20Streak/README_EN.md) | `Database` | Hard | 🔒 |
306306
| 3401 | [Find Circular Gift Exchange Chains](/solution/3400-3499/3401.Find%20Circular%20Gift%20Exchange%20Chains/README_EN.md) | `Database` | Hard | 🔒 |
307307
| 3415 | [Find Products with Three Consecutive Digits](/solution/3400-3499/3415.Find%20Products%20with%20Three%20Consecutive%20Digits/README_EN.md) | `Database` | Easy | 🔒 |
308+
| 3421 | [Find Students Who Improved](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README_EN.md) | | Medium | |
308309

309310
## Copyright
310311

solution/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -3431,6 +3431,7 @@
34313431
| 3418 | [机器人可以获得的最大金币数](/solution/3400-3499/3418.Maximum%20Amount%20of%20Money%20Robot%20Can%20Earn/README.md) | | 中等 | 第 432 场周赛 |
34323432
| 3419 | [图的最大边权的最小值](/solution/3400-3499/3419.Minimize%20the%20Maximum%20Edge%20Weight%20of%20Graph/README.md) | | 中等 | 第 432 场周赛 |
34333433
| 3420 | [统计 K 次操作以内得到非递减子数组的数目](/solution/3400-3499/3420.Count%20Non-Decreasing%20Subarrays%20After%20K%20Operations/README.md) | | 困难 | 第 432 场周赛 |
3434+
| 3421 | [查找进步的学生](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README.md) | | 中等 | |
34343435

34353436
## 版权
34363437

solution/README_EN.md

+1
Original file line numberDiff line numberDiff line change
@@ -3429,6 +3429,7 @@ Press <kbd>Control</kbd> + <kbd>F</kbd>(or <kbd>Command</kbd> + <kbd>F</kbd> on
34293429
| 3418 | [Maximum Amount of Money Robot Can Earn](/solution/3400-3499/3418.Maximum%20Amount%20of%20Money%20Robot%20Can%20Earn/README_EN.md) | | Medium | Weekly Contest 432 |
34303430
| 3419 | [Minimize the Maximum Edge Weight of Graph](/solution/3400-3499/3419.Minimize%20the%20Maximum%20Edge%20Weight%20of%20Graph/README_EN.md) | | Medium | Weekly Contest 432 |
34313431
| 3420 | [Count Non-Decreasing Subarrays After K Operations](/solution/3400-3499/3420.Count%20Non-Decreasing%20Subarrays%20After%20K%20Operations/README_EN.md) | | Hard | Weekly Contest 432 |
3432+
| 3421 | [Find Students Who Improved](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README_EN.md) | | Medium | |
34323433

34333434
## Copyright
34343435

0 commit comments

Comments
 (0)