Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update solutions to lc problems: No.0180,0610,1164 #1850

Merged
merged 3 commits into from
Oct 20, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
"overrides": [
{
"files": [
"solution/0100-0199/0180.Consecutive Numbers/Solution.sql",
"solution/0500-0599/0550.Game Play Analysis IV/Solution.sql",
"solution/0500-0599/0578.Get Highest Answer Rate Question/Solution.sql",
"solution/0600-0699/0610.Triangle Judgement/Solution.sql",
@@ -55,4 +56,4 @@
}
}
]
}
}
52 changes: 44 additions & 8 deletions solution/0100-0199/0180.Consecutive Numbers/README.md
Original file line number Diff line number Diff line change
@@ -57,26 +57,62 @@ Result 表:

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

**方法一:两次连接**

我们可以使用两次连接来解决这个问题。

我们首先进行一次自连接,连接条件是 `l1.num = l2.num` 并且 `l1.id = l2.id - 1`,这样我们就可以找出所有至少连续出现两次的数字。然后,我们再进行一次自连接,连接条件是 `l2.num = l3.num` 并且 `l2.id = l3.id - 1`,这样我们就可以找出所有至少连续出现三次的数字。最后,我们只需要筛选出去重的 `l2.num` 即可。

**方法二:窗口函数**

我们可以使用窗口函数 `LAG` 和 `LEAD` 来获取上一行的 `num` 和下一行的 `num`,记录在字段 $a$ 和 $b$ 中。最后,我们只需要筛选出 $a =num$ 并且 $b = num$ 的行,这些行就是至少连续出现三次的数字。注意,我们需要使用 `DISTINCT` 关键字来对结果去重。

我们也可以对数字进行分组,具体做法是使用 `IF` 函数来判断当前行与前一行的 `num` 是否相等,如果相等则记为 $0$,否则记为 $1$,然后使用窗口函数 `SUM` 来计算前缀和,这样计算出的前缀和就是分组的标识。最后,我们只需要按照分组标识进行分组,然后筛选出每组中的行数大于等于 $3$ 的数字即可。同样,我们需要使用 `DISTINCT` 关键字来对结果去重。

<!-- tabs:start -->

### **SQL**

```sql
# Write your MySQL query statement below
SELECT DISTINCT l2.num AS ConsecutiveNums
FROM
Logs AS l1
JOIN Logs AS l2 ON l1.id = l2.id - 1 AND l1.num = l2.num
JOIN Logs AS l3 ON l2.id = l3.id - 1 AND l2.num = l3.num;
```

```sql
# Write your MySQL query statement below
WITH
T AS (
SELECT
*,
LAG(num) OVER () AS a,
LEAD(num) OVER () AS b
FROM Logs
)
SELECT DISTINCT num AS ConsecutiveNums
FROM T
WHERE a = num AND b = num;
```

```sql
# Write your MySQL query statement below
WITH
t AS (
T AS (
SELECT
*,
CASE
WHEN (LAG(num) OVER (ORDER BY id)) = num THEN 0
ELSE 1
END AS mark
IF(num = (LAG(num) OVER ()), 0, 1) AS st
FROM Logs
),
p AS (SELECT num, SUM(mark) OVER (ORDER BY id) AS gid FROM t)
S AS (
SELECT *, SUM(st) OVER (ORDER BY id) AS p
FROM T
)
SELECT DISTINCT num AS ConsecutiveNums
FROM p
GROUP BY gid
FROM S
GROUP BY p
HAVING COUNT(1) >= 3;
```

52 changes: 44 additions & 8 deletions solution/0100-0199/0180.Consecutive Numbers/README_EN.md
Original file line number Diff line number Diff line change
@@ -53,26 +53,62 @@ Logs table:

## Solutions

**Solution 1: Two Joins**

We can use two joins to solve this problem.

First, we perform a self-join with the condition `l1.num = l2.num` and `l1.id = l2.id - 1`, so that we can find all numbers that appear at least twice in a row. Then, we perform another self-join with the condition `l2.num = l3.num` and `l2.id = l3.id - 1`, so that we can find all numbers that appear at least three times in a row. Finally, we only need to select the distinct `l2.num`.

**Solution 2: Window Function**

We can use the window functions `LAG` and `LEAD` to obtain the `num` of the previous row and the next row of the current row, and record them in the fields $a$ and $b$, respectively. Finally, we only need to filter out the rows where $a = num$ and $b = num$, which are the numbers that appear at least three times in a row. Note that we need to use the `DISTINCT` keyword to remove duplicates from the results.

We can also group the numbers by using the `IF` function to determine whether the `num` of the current row is equal to the `num` of the previous row. If they are equal, we set it to $0$, otherwise we set it to $1$. Then, we use the window function `SUM` to calculate the prefix sum, which is the grouping identifier. Finally, we only need to group by the grouping identifier and filter out the numbers with a row count greater than or equal to $3$ in each group. Similarly, we need to use the `DISTINCT` keyword to remove duplicates from the results.

<!-- tabs:start -->

### **SQL**

```sql
# Write your MySQL query statement below
SELECT DISTINCT l2.num AS ConsecutiveNums
FROM
Logs AS l1
JOIN Logs AS l2 ON l1.id = l2.id - 1 AND l1.num = l2.num
JOIN Logs AS l3 ON l2.id = l3.id - 1 AND l2.num = l3.num;
```

```sql
# Write your MySQL query statement below
WITH
T AS (
SELECT
*,
LAG(num) OVER () AS a,
LEAD(num) OVER () AS b
FROM Logs
)
SELECT DISTINCT num AS ConsecutiveNums
FROM T
WHERE a = num AND b = num;
```

```sql
# Write your MySQL query statement below
WITH
t AS (
T AS (
SELECT
*,
CASE
WHEN (LAG(num) OVER (ORDER BY id)) = num THEN 0
ELSE 1
END AS mark
IF(num = (LAG(num) OVER ()), 0, 1) AS st
FROM Logs
),
p AS (SELECT num, SUM(mark) OVER (ORDER BY id) AS gid FROM t)
S AS (
SELECT *, SUM(st) OVER (ORDER BY id) AS p
FROM T
)
SELECT DISTINCT num AS ConsecutiveNums
FROM p
GROUP BY gid
FROM S
GROUP BY p
HAVING COUNT(1) >= 3;
```

16 changes: 8 additions & 8 deletions solution/0100-0199/0180.Consecutive Numbers/Solution.sql
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Write your MySQL query statement below
WITH
t AS (
T AS (
SELECT
*,
CASE
WHEN (LAG(num) OVER (ORDER BY id)) = num THEN 0
ELSE 1
END AS mark
IF(num = (LAG(num) OVER ()), 0, 1) AS st
FROM Logs
),
p AS (SELECT num, SUM(mark) OVER (ORDER BY id) AS gid FROM t)
S AS (
SELECT *, SUM(st) OVER (ORDER BY id) AS p
FROM T
)
SELECT DISTINCT num AS ConsecutiveNums
FROM p
GROUP BY gid
FROM S
GROUP BY p
HAVING COUNT(1) >= 3;
4 changes: 2 additions & 2 deletions solution/0600-0699/0610.Triangle Judgement/README.md
Original file line number Diff line number Diff line change
@@ -53,9 +53,9 @@ Triangle 表:

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

**方法一:if 语句 + 三角形判断条件**
**方法一:IF 语句 + 三角形判断条件**

三条边能否构成三角形的条件是:任意两边之和大于第三边。因此,我们可以使用 `if` 语句来判断是否满足这个条件,如果满足则返回 `Yes`,否则返回 `No`。
三条边能否构成三角形的条件是:任意两边之和大于第三边。因此,我们可以使用 `IF` 语句来判断是否满足这个条件,如果满足则返回 `Yes`,否则返回 `No`。

<!-- tabs:start -->

4 changes: 4 additions & 0 deletions solution/0600-0699/0610.Triangle Judgement/README_EN.md
Original file line number Diff line number Diff line change
@@ -49,6 +49,10 @@ Triangle table:

## Solutions

**Solution 1: IF Statement + Triangle Inequality**

The condition for whether three sides can form a triangle is that the sum of any two sides is greater than the third side. Therefore, we can use an `IF` statement to determine whether this condition is satisfied. If it is satisfied, we return `Yes`, otherwise we return `No`.

<!-- tabs:start -->

### **SQL**
41 changes: 18 additions & 23 deletions solution/1100-1199/1164.Product Price at a Given Date/README.md
Original file line number Diff line number Diff line change
@@ -57,38 +57,33 @@ Products 表:

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

**方法一:子查询 + 连接**

我们可以使用子查询,找出每个产品在给定日期之前最后一次价格变更的价格,记录在 `P` 表中。然后,我们再找出所有产品的 `product_id`,记录在 `T` 表中。最后,我们将 `T` 表和 `P` 表按照 `product_id` 进行左连接,即可得到最终结果。

<!-- tabs:start -->

### **SQL**

```sql
# Write your MySQL query statement below
SELECT
p1.product_id AS product_id,
IFNULL(p2.price, 10) AS price
FROM
(
SELECT DISTINCT
(product_id) AS product_id
WITH
T AS (SELECT DISTINCT product_id FROM Products),
P AS (
SELECT product_id, new_price AS price
FROM Products
) AS p1
LEFT JOIN (
SELECT
t1.product_id,
t1.new_price AS price
FROM
Products AS t1
JOIN (
SELECT
product_id,
MAX(change_date) AS change_date
WHERE
(product_id, change_date) IN (
SELECT product_id, MAX(change_date) AS change_date
FROM Products
WHERE change_date <= '2019-08-16'
GROUP BY product_id
) AS t2
ON t1.product_id = t2.product_id AND t1.change_date = t2.change_date
) AS p2
ON p1.product_id = p2.product_id;
GROUP BY 1
)
)
SELECT product_id, IFNULL(price, 10) AS price
FROM
T
LEFT JOIN P USING (product_id);
```

```sql
41 changes: 18 additions & 23 deletions solution/1100-1199/1164.Product Price at a Given Date/README_EN.md
Original file line number Diff line number Diff line change
@@ -53,38 +53,33 @@ Products table:

## Solutions

**Solution 1: Subquery + Join**

We can use a subquery to find the price of the last price change for each product before the given date, and record it in the `P` table. Then, we can find all `product_id`s in the `T` table. Finally, we can left join the `T` table with the `P` table on `product_id` to get the final result.

<!-- tabs:start -->

### **SQL**

```sql
# Write your MySQL query statement below
SELECT
p1.product_id AS product_id,
IFNULL(p2.price, 10) AS price
FROM
(
SELECT DISTINCT
(product_id) AS product_id
WITH
T AS (SELECT DISTINCT product_id FROM Products),
P AS (
SELECT product_id, new_price AS price
FROM Products
) AS p1
LEFT JOIN (
SELECT
t1.product_id,
t1.new_price AS price
FROM
Products AS t1
JOIN (
SELECT
product_id,
MAX(change_date) AS change_date
WHERE
(product_id, change_date) IN (
SELECT product_id, MAX(change_date) AS change_date
FROM Products
WHERE change_date <= '2019-08-16'
GROUP BY product_id
) AS t2
ON t1.product_id = t2.product_id AND t1.change_date = t2.change_date
) AS p2
ON p1.product_id = p2.product_id;
GROUP BY 1
)
)
SELECT product_id, IFNULL(price, 10) AS price
FROM
T
LEFT JOIN P USING (product_id);
```

```sql
32 changes: 13 additions & 19 deletions solution/1100-1199/1164.Product Price at a Given Date/Solution.sql
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
# Write your MySQL query statement below
WITH
T AS (SELECT DISTINCT product_id FROM Products),
P AS (
SELECT p1.product_id, new_price, change_date
FROM
(
SELECT DISTINCT product_id
SELECT product_id, new_price AS price
FROM Products
WHERE
(product_id, change_date) IN (
SELECT product_id, MAX(change_date) AS change_date
FROM Products
) AS p1
LEFT JOIN Products AS p2
ON p1.product_id = p2.product_id AND p2.change_date <= '2019-08-16'
),
T AS (
SELECT
*,
RANK() OVER (
PARTITION BY product_id
ORDER BY change_date DESC
) AS rk
FROM P
WHERE change_date <= '2019-08-16'
GROUP BY 1
)
)
SELECT product_id, IFNULL(new_price, 10) AS price
FROM T
WHERE rk = 1;
SELECT product_id, IFNULL(price, 10) AS price
FROM
T
LEFT JOIN P USING (product_id);