Skip to content

Commit

Permalink
feat: add solutions to lc problem: No.3421
Browse files Browse the repository at this point in the history
No.3421.Find Students Who Improved
  • Loading branch information
yanglbme committed Jan 14, 2025
1 parent 6a244ec commit 63f2efb
Show file tree
Hide file tree
Showing 8 changed files with 340 additions and 2 deletions.
4 changes: 2 additions & 2 deletions solution/0500-0599/0563.Binary Tree Tilt/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ tags:
<pre>
<strong>Input:</strong> root = [1,2,3]
<strong>Output:</strong> 1
<strong>Explanation:</strong>
<strong>Explanation:</strong>
Tilt of node 2 : |0-0| = 0 (no children)
Tilt of node 3 : |0-0| = 0 (no children)
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)
Expand All @@ -40,7 +40,7 @@ Sum of every tilt : 0 + 0 + 1 = 1
<pre>
<strong>Input:</strong> root = [4,2,9,3,5,null,7]
<strong>Output:</strong> 15
<strong>Explanation:</strong>
<strong>Explanation:</strong>
Tilt of node 3 : |0-0| = 0 (no children)
Tilt of node 5 : |0-0| = 0 (no children)
Tilt of node 7 : |0-0| = 0 (no children)
Expand Down
151 changes: 151 additions & 0 deletions solution/3400-3499/3421.Find Students Who Improved/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
---
comments: true
difficulty: 中等
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README.md
tags:
- 数据库
---

<!-- problem:start -->

# [3421. 查找进步的学生](https://leetcode.cn/problems/find-students-who-improved)

[English Version](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README_EN.md)

## 题目描述

<!-- description:start -->

<p>表:<code>Scores</code></p>

<pre>
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| student_id | int |
| subject | varchar |
| score | int |
| exam_date | varchar |
+-------------+---------+
(student_id, subject, exam_date) 是这张表的主键。
每一行包含有关学生在特定考试日期特定科目成绩的信息。分数范围从 0 到 100(包括边界)。
</pre>

<p>编写一个解决方案来查找 <strong>进步的学生</strong>。如果 <strong>同时</strong> 满足以下两个条件,则该学生被认为是进步的:</p>

<ul>
<li>在 <strong>同一科目</strong>&nbsp;至少有两个不同日期的考试。</li>
<li>他们在该学科&nbsp;<strong>最近的分数</strong>&nbsp;比他们 <strong>第一次的分数更高。</strong></li>
</ul>

<p>返回结果表以&nbsp;<code>student_id</code>,<code>subject</code> <strong>升序</strong>&nbsp;排序。</p>

<p>结果格式如下所示。</p>

<p>&nbsp;</p>

<p><strong class="example">示例:</strong></p>

<div class="example-block">
<p><strong>输入:</strong></p>

<p>Scores 表:</p>

<pre class="example-io">
+------------+----------+-------+------------+
| student_id | subject | score | exam_date |
+------------+----------+-------+------------+
| 101 | Math | 70 | 15-01-2023 |
| 101 | Math | 85 | 15-02-2023 |
| 101 | Physics | 65 | 15-01-2023 |
| 101 | Physics | 60 | 15-02-2023 |
| 102 | Math | 80 | 15-01-2023 |
| 102 | Math | 85 | 15-02-2023 |
| 103 | Math | 90 | 15-01-2023 |
| 104 | Physics | 75 | 15-01-2023 |
| 104 | Physics | 85 | 15-02-2023 |
+------------+----------+-------+------------+
</pre>

<p><strong>输出:</strong></p>

<pre class="example-io">
+------------+----------+-------------+--------------+
| student_id | subject | first_score | latest_score |
+------------+----------+-------------+--------------+
| 101 | Math | 70 | 85 |
| 102 | Math | 80 | 85 |
| 104 | Physics | 75 | 85 |
+------------+----------+-------------+--------------+
</pre>

<p><strong>解释:</strong></p>

<ul>
<li>学生 101 的数学:从 70 分进步到 85 分。</li>
<li>学生 101 的物理:没有进步(从 65 分退步到 60分)</li>
<li>学生 102 的数学:从 80 进步到 85 分。</li>
<li>学生 103 的数学:只有一次考试,不符合资格。</li>
<li>学生 104 in Physics:从 75 分进步到 85 分。</li>
</ul>

<p>结果表以 student_id,subject 升序排序。</p>
</div>

<!-- description:end -->

## 解法

<!-- solution:start -->

### 方法一:窗口函数 + 子连接 + 条件过滤

首先,我们使用窗口函数 `ROW_NUMBER()` 计算每个学生在每个科目中的考试日期的排名,分别计算出每个学生在每个科目中的第一次考试和最近一次考试的排名。

然后,我们使用子连接 `JOIN` 操作将第一次考试和最近一次考试的分数连接在一起,最后根据题目要求筛选出最近一次考试的分数比第一次考试的分数高的学生。

<!-- tabs:start -->

#### MySQL

```sql
WITH
RankedScores AS (
SELECT
student_id,
subject,
score,
exam_date,
ROW_NUMBER() OVER (
PARTITION BY student_id, subject
ORDER BY exam_date ASC
) AS rn_first,
ROW_NUMBER() OVER (
PARTITION BY student_id, subject
ORDER BY exam_date DESC
) AS rn_latest
FROM Scores
),
FirstAndLatestScores AS (
SELECT
f.student_id,
f.subject,
f.score AS first_score,
l.score AS latest_score
FROM
RankedScores f
JOIN RankedScores l ON f.student_id = l.student_id AND f.subject = l.subject
WHERE f.rn_first = 1 AND l.rn_latest = 1
)
SELECT
*
FROM FirstAndLatestScores
WHERE latest_score > first_score
ORDER BY 1, 2;
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- problem:end -->
150 changes: 150 additions & 0 deletions solution/3400-3499/3421.Find Students Who Improved/README_EN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
---
comments: true
difficulty: Medium
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README_EN.md
tags:
- Database
---

<!-- problem:start -->

# [3421. Find Students Who Improved](https://leetcode.com/problems/find-students-who-improved)

[中文文档](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README.md)

## Description

<!-- description:start -->

<p>Table: <code>Scores</code></p>

<pre>
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| student_id | int |
| subject | varchar |
| score | int |
| exam_date | varchar |
+-------------+---------+
(student_id, subject, exam_date) is the primary key for this table.
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).
</pre>

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

<ul>
<li>Have taken exams in the <strong>same subject</strong> on at least two different dates</li>
<li>Their <strong>latest score</strong> in that subject is <strong>higher</strong> than their <strong>first score</strong></li>
</ul>

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

<p>The result format is in the following example.</p>

<p>&nbsp;</p>
<p><strong class="example">Example:</strong></p>

<div class="example-block">
<p><strong>Input:</strong></p>

<p>Scores table:</p>

<pre class="example-io">
+------------+----------+-------+------------+
| student_id | subject | score | exam_date |
+------------+----------+-------+------------+
| 101 | Math | 70 | 15-01-2023 |
| 101 | Math | 85 | 15-02-2023 |
| 101 | Physics | 65 | 15-01-2023 |
| 101 | Physics | 60 | 15-02-2023 |
| 102 | Math | 80 | 15-01-2023 |
| 102 | Math | 85 | 15-02-2023 |
| 103 | Math | 90 | 15-01-2023 |
| 104 | Physics | 75 | 15-01-2023 |
| 104 | Physics | 85 | 15-02-2023 |
+------------+----------+-------+------------+
</pre>

<p><strong>Output:</strong></p>

<pre class="example-io">
+------------+----------+-------------+--------------+
| student_id | subject | first_score | latest_score |
+------------+----------+-------------+--------------+
| 101 | Math | 70 | 85 |
| 102 | Math | 80 | 85 |
| 104 | Physics | 75 | 85 |
+------------+----------+-------------+--------------+
</pre>

<p><strong>Explanation:</strong></p>

<ul>
<li>Student 101 in Math: Improved from 70 to 85</li>
<li>Student 101 in Physics: No improvement (dropped from 65 to 60)</li>
<li>Student 102 in Math: Improved from 80 to 85</li>
<li>Student 103 in Math: Only one exam, not eligible</li>
<li>Student 104 in Physics: Improved from 75 to 85</li>
</ul>

<p>Result table is ordered by student_id, subject.</p>
</div>

<!-- description:end -->

## Solutions

<!-- solution:start -->

### Solution 1: Window Function + Subquery + Conditional Filtering

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.

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.

<!-- tabs:start -->

#### MySQL

```sql
WITH
RankedScores AS (
SELECT
student_id,
subject,
score,
exam_date,
ROW_NUMBER() OVER (
PARTITION BY student_id, subject
ORDER BY exam_date ASC
) AS rn_first,
ROW_NUMBER() OVER (
PARTITION BY student_id, subject
ORDER BY exam_date DESC
) AS rn_latest
FROM Scores
),
FirstAndLatestScores AS (
SELECT
f.student_id,
f.subject,
f.score AS first_score,
l.score AS latest_score
FROM
RankedScores f
JOIN RankedScores l ON f.student_id = l.student_id AND f.subject = l.subject
WHERE f.rn_first = 1 AND l.rn_latest = 1
)
SELECT
*
FROM FirstAndLatestScores
WHERE latest_score > first_score
ORDER BY 1, 2;
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- problem:end -->
33 changes: 33 additions & 0 deletions solution/3400-3499/3421.Find Students Who Improved/Solution.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
WITH
RankedScores AS (
SELECT
student_id,
subject,
score,
exam_date,
ROW_NUMBER() OVER (
PARTITION BY student_id, subject
ORDER BY exam_date ASC
) AS rn_first,
ROW_NUMBER() OVER (
PARTITION BY student_id, subject
ORDER BY exam_date DESC
) AS rn_latest
FROM Scores
),
FirstAndLatestScores AS (
SELECT
f.student_id,
f.subject,
f.score AS first_score,
l.score AS latest_score
FROM
RankedScores f
JOIN RankedScores l ON f.student_id = l.student_id AND f.subject = l.subject
WHERE f.rn_first = 1 AND l.rn_latest = 1
)
SELECT
*
FROM FirstAndLatestScores
WHERE latest_score > first_score
ORDER BY 1, 2;
1 change: 1 addition & 0 deletions solution/DATABASE_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@
| 3390 | [Longest Team Pass Streak](/solution/3300-3399/3390.Longest%20Team%20Pass%20Streak/README.md) | `数据库` | 困难 | 🔒 |
| 3401 | [Find Circular Gift Exchange Chains](/solution/3400-3499/3401.Find%20Circular%20Gift%20Exchange%20Chains/README.md) | `数据库` | 困难 | 🔒 |
| 3415 | [查找具有三个连续数字的产品](/solution/3400-3499/3415.Find%20Products%20with%20Three%20Consecutive%20Digits/README.md) | `数据库` | 简单 | 🔒 |
| 3421 | [查找进步的学生](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README.md) | | 中等 | |

## 版权

Expand Down
1 change: 1 addition & 0 deletions solution/DATABASE_README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ Press <kbd>Control</kbd> + <kbd>F</kbd>(or <kbd>Command</kbd> + <kbd>F</kbd> on
| 3390 | [Longest Team Pass Streak](/solution/3300-3399/3390.Longest%20Team%20Pass%20Streak/README_EN.md) | `Database` | Hard | 🔒 |
| 3401 | [Find Circular Gift Exchange Chains](/solution/3400-3499/3401.Find%20Circular%20Gift%20Exchange%20Chains/README_EN.md) | `Database` | Hard | 🔒 |
| 3415 | [Find Products with Three Consecutive Digits](/solution/3400-3499/3415.Find%20Products%20with%20Three%20Consecutive%20Digits/README_EN.md) | `Database` | Easy | 🔒 |
| 3421 | [Find Students Who Improved](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README_EN.md) | | Medium | |

## Copyright

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

## 版权

Expand Down
1 change: 1 addition & 0 deletions solution/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -3429,6 +3429,7 @@ Press <kbd>Control</kbd> + <kbd>F</kbd>(or <kbd>Command</kbd> + <kbd>F</kbd> on
| 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 |
| 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 |
| 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 |
| 3421 | [Find Students Who Improved](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README_EN.md) | | Medium | |

## Copyright

Expand Down

0 comments on commit 63f2efb

Please sign in to comment.