Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

feat: add sql solution to lc problem: No.3451 #4057

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

Merged
merged 1 commit into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ node_modules/
/solution/3100-3199/3150.Invalid Tweets II/Solution.sql
/solution/3100-3199/3198.Find Cities in Each State/Solution.sql
/solution/3300-3399/3328.Find Cities in Each State II/Solution.sql
/solution/3400-3499/3451.Find Invalid IP Addresses/Solution.sql
162 changes: 162 additions & 0 deletions solution/3400-3499/3451.Find Invalid IP Addresses/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
---
comments: true
difficulty: 困难
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3400-3499/3451.Find%20Invalid%20IP%20Addresses/README.md
tags:
- 数据库
---

<!-- problem:start -->

# [3451. Find Invalid IP Addresses](https://leetcode.cn/problems/find-invalid-ip-addresses)

[English Version](/solution/3400-3499/3451.Find%20Invalid%20IP%20Addresses/README_EN.md)

## 题目描述

<!-- description:start -->

<p>Table: <code> logs</code></p>

<pre>
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| log_id | int |
| ip | varchar |
| status_code | int |
+-------------+---------+
log_id is the unique key for this table.
Each row contains server access log information including IP address and HTTP status code.
</pre>

<p>Write a solution to find <strong>invalid IP addresses</strong>. An IPv4 address is invalid if it meets any of these conditions:</p>

<ul>
<li>Contains numbers <strong>greater than</strong> <code>255</code> in any octet</li>
<li>Has <strong>leading zeros</strong> in any octet (like <code>01.02.03.04</code>)</li>
<li>Has <strong>less or more</strong> than <code>4</code> octets</li>
</ul>

<p>Return <em>the result table </em><em>ordered by</em> <code>invalid_count</code>,&nbsp;<code>ip</code>&nbsp;<em>in <strong>descending</strong> order respectively</em>.&nbsp;</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>logs table:</p>

<pre class="example-io">
+--------+---------------+-------------+
| log_id | ip | status_code |
+--------+---------------+-------------+
| 1 | 192.168.1.1 | 200 |
| 2 | 256.1.2.3 | 404 |
| 3 | 192.168.001.1 | 200 |
| 4 | 192.168.1.1 | 200 |
| 5 | 192.168.1 | 500 |
| 6 | 256.1.2.3 | 404 |
| 7 | 192.168.001.1 | 200 |
+--------+---------------+-------------+
</pre>

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

<pre class="example-io">
+---------------+--------------+
| ip | invalid_count|
+---------------+--------------+
| 256.1.2.3 | 2 |
| 192.168.001.1 | 2 |
| 192.168.1 | 1 |
+---------------+--------------+
</pre>

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

<ul>
<li>256.1.2.3&nbsp;is invalid because 256 &gt; 255</li>
<li>192.168.001.1&nbsp;is invalid because of leading zeros</li>
<li>192.168.1&nbsp;is invalid because it has only 3 octets</li>
</ul>

<p>The output table is ordered by invalid_count, ip in descending order respectively.</p>
</div>

<!-- description:end -->

## 解法

<!-- solution:start -->

### 方法一:模拟

我们可以根据题意,判断 IP 地址是否不合法,判断的条件有:

1. IP 地址中的 `.` 的个数不等于 $3$;
2. IP 地址中的某个 octet 以 `0` 开头;
3. IP 地址中的某个 octet 大于 $255$。

然后我们将不合法的 IP 地址进行分组,并统计每个不合法的 IP 地址的个数 `invalid_count`,最后按照 `invalid_count` 和 `ip` 降序排序。

<!-- tabs:start -->

#### MySQL

```sql
SELECT
ip,
COUNT(*) AS invalid_count
FROM logs
WHERE
LENGTH(ip) - LENGTH(REPLACE(ip, '.', '')) != 3
OR SUBSTRING_INDEX(ip, '.', 1) REGEXP '^0[0-9]'
OR SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 2), '.', -1) REGEXP '^0[0-9]'
OR SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 3), '.', -1) REGEXP '^0[0-9]'
OR SUBSTRING_INDEX(ip, '.', -1) REGEXP '^0[0-9]'
OR SUBSTRING_INDEX(ip, '.', 1) > 255
OR SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 2), '.', -1) > 255
OR SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 3), '.', -1) > 255
OR SUBSTRING_INDEX(ip, '.', -1) > 255
GROUP BY 1
ORDER BY 2 DESC, 1 DESC;
```

#### Pandas

```python
import pandas as pd


def find_invalid_ips(logs: pd.DataFrame) -> pd.DataFrame:
def is_valid_ip(ip: str) -> bool:
octets = ip.split(".")
if len(octets) != 4:
return False
for octet in octets:
if not octet.isdigit():
return False
value = int(octet)
if not 0 <= value <= 255 or octet != str(value):
return False
return True

logs["is_valid"] = logs["ip"].apply(is_valid_ip)
invalid_ips = logs[~logs["is_valid"]]
invalid_count = invalid_ips["ip"].value_counts().reset_index()
invalid_count.columns = ["ip", "invalid_count"]
result = invalid_count.sort_values(
by=["invalid_count", "ip"], ascending=[False, False]
)
return result
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- problem:end -->
162 changes: 162 additions & 0 deletions solution/3400-3499/3451.Find Invalid IP Addresses/README_EN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
---
comments: true
difficulty: Hard
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3400-3499/3451.Find%20Invalid%20IP%20Addresses/README_EN.md
tags:
- Database
---

<!-- problem:start -->

# [3451. Find Invalid IP Addresses](https://leetcode.com/problems/find-invalid-ip-addresses)

[中文文档](/solution/3400-3499/3451.Find%20Invalid%20IP%20Addresses/README.md)

## Description

<!-- description:start -->

<p>Table: <code> logs</code></p>

<pre>
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| log_id | int |
| ip | varchar |
| status_code | int |
+-------------+---------+
log_id is the unique key for this table.
Each row contains server access log information including IP address and HTTP status code.
</pre>

<p>Write a solution to find <strong>invalid IP addresses</strong>. An IPv4 address is invalid if it meets any of these conditions:</p>

<ul>
<li>Contains numbers <strong>greater than</strong> <code>255</code> in any octet</li>
<li>Has <strong>leading zeros</strong> in any octet (like <code>01.02.03.04</code>)</li>
<li>Has <strong>less or more</strong> than <code>4</code> octets</li>
</ul>

<p>Return <em>the result table </em><em>ordered by</em> <code>invalid_count</code>,&nbsp;<code>ip</code>&nbsp;<em>in <strong>descending</strong> order respectively</em>.&nbsp;</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>logs table:</p>

<pre class="example-io">
+--------+---------------+-------------+
| log_id | ip | status_code |
+--------+---------------+-------------+
| 1 | 192.168.1.1 | 200 |
| 2 | 256.1.2.3 | 404 |
| 3 | 192.168.001.1 | 200 |
| 4 | 192.168.1.1 | 200 |
| 5 | 192.168.1 | 500 |
| 6 | 256.1.2.3 | 404 |
| 7 | 192.168.001.1 | 200 |
+--------+---------------+-------------+
</pre>

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

<pre class="example-io">
+---------------+--------------+
| ip | invalid_count|
+---------------+--------------+
| 256.1.2.3 | 2 |
| 192.168.001.1 | 2 |
| 192.168.1 | 1 |
+---------------+--------------+
</pre>

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

<ul>
<li>256.1.2.3&nbsp;is invalid because 256 &gt; 255</li>
<li>192.168.001.1&nbsp;is invalid because of leading zeros</li>
<li>192.168.1&nbsp;is invalid because it has only 3 octets</li>
</ul>

<p>The output table is ordered by invalid_count, ip in descending order respectively.</p>
</div>

<!-- description:end -->

## Solutions

<!-- solution:start -->

### Solution 1: Simulation

We can determine if an IP address is invalid based on the following conditions:

1. The number of `.` in the IP address is not equal to $3$;
2. Any octet in the IP address starts with `0`;
3. Any octet in the IP address is greater than $255$.

Then we group the invalid IP addresses and count the occurrences of each invalid IP address `invalid_count`, and finally sort by `invalid_count` and `ip` in descending order.

<!-- tabs:start -->

#### MySQL

```sql
SELECT
ip,
COUNT(*) AS invalid_count
FROM logs
WHERE
LENGTH(ip) - LENGTH(REPLACE(ip, '.', '')) != 3
OR SUBSTRING_INDEX(ip, '.', 1) REGEXP '^0[0-9]'
OR SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 2), '.', -1) REGEXP '^0[0-9]'
OR SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 3), '.', -1) REGEXP '^0[0-9]'
OR SUBSTRING_INDEX(ip, '.', -1) REGEXP '^0[0-9]'
OR SUBSTRING_INDEX(ip, '.', 1) > 255
OR SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 2), '.', -1) > 255
OR SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 3), '.', -1) > 255
OR SUBSTRING_INDEX(ip, '.', -1) > 255
GROUP BY 1
ORDER BY 2 DESC, 1 DESC;
```

#### Pandas

```python
import pandas as pd


def find_invalid_ips(logs: pd.DataFrame) -> pd.DataFrame:
def is_valid_ip(ip: str) -> bool:
octets = ip.split(".")
if len(octets) != 4:
return False
for octet in octets:
if not octet.isdigit():
return False
value = int(octet)
if not 0 <= value <= 255 or octet != str(value):
return False
return True

logs["is_valid"] = logs["ip"].apply(is_valid_ip)
invalid_ips = logs[~logs["is_valid"]]
invalid_count = invalid_ips["ip"].value_counts().reset_index()
invalid_count.columns = ["ip", "invalid_count"]
result = invalid_count.sort_values(
by=["invalid_count", "ip"], ascending=[False, False]
)
return result
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- problem:end -->
24 changes: 24 additions & 0 deletions solution/3400-3499/3451.Find Invalid IP Addresses/Solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import pandas as pd


def find_invalid_ips(logs: pd.DataFrame) -> pd.DataFrame:
def is_valid_ip(ip: str) -> bool:
octets = ip.split(".")
if len(octets) != 4:
return False
for octet in octets:
if not octet.isdigit():
return False
value = int(octet)
if not 0 <= value <= 255 or octet != str(value):
return False
return True

logs["is_valid"] = logs["ip"].apply(is_valid_ip)
invalid_ips = logs[~logs["is_valid"]]
invalid_count = invalid_ips["ip"].value_counts().reset_index()
invalid_count.columns = ["ip", "invalid_count"]
result = invalid_count.sort_values(
by=["invalid_count", "ip"], ascending=[False, False]
)
return result
19 changes: 19 additions & 0 deletions solution/3400-3499/3451.Find Invalid IP Addresses/Solution.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
SELECT
ip,
COUNT(*) AS invalid_count
FROM logs
WHERE
LENGTH(ip) - LENGTH(REPLACE(ip, '.', '')) != 3

OR SUBSTRING_INDEX(ip, '.', 1) REGEXP '^0[0-9]'
OR SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 2), '.', -1) REGEXP '^0[0-9]'
OR SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 3), '.', -1) REGEXP '^0[0-9]'
OR SUBSTRING_INDEX(ip, '.', -1) REGEXP '^0[0-9]'

OR SUBSTRING_INDEX(ip, '.', 1) > 255
OR SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 2), '.', -1) > 255
OR SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 3), '.', -1) > 255
OR SUBSTRING_INDEX(ip, '.', -1) > 255

GROUP BY 1
ORDER BY 2 DESC, 1 DESC;
1 change: 1 addition & 0 deletions solution/DATABASE_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@
| 3415 | [查找具有三个连续数字的产品](/solution/3400-3499/3415.Find%20Products%20with%20Three%20Consecutive%20Digits/README.md) | `数据库` | 简单 | 🔒 |
| 3421 | [查找进步的学生](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README.md) | `数据库` | 中等 | |
| 3436 | [查找合法邮箱](/solution/3400-3499/3436.Find%20Valid%20Emails/README.md) | `数据库` | 简单 | |
| 3451 | [Find Invalid IP Addresses](/solution/3400-3499/3451.Find%20Invalid%20IP%20Addresses/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 @@ -307,6 +307,7 @@ Press <kbd>Control</kbd> + <kbd>F</kbd>(or <kbd>Command</kbd> + <kbd>F</kbd> on
| 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) | `Database` | Medium | |
| 3436 | [Find Valid Emails](/solution/3400-3499/3436.Find%20Valid%20Emails/README_EN.md) | `Database` | Easy | |
| 3451 | [Find Invalid IP Addresses](/solution/3400-3499/3451.Find%20Invalid%20IP%20Addresses/README_EN.md) | | Hard | |

## Copyright

Expand Down
1 change: 1 addition & 0 deletions solution/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3461,6 +3461,7 @@
| 3448 | [统计可以被最后一个数位整除的子字符串数目](/solution/3400-3499/3448.Count%20Substrings%20Divisible%20By%20Last%20Digit/README.md) | | 困难 | 第 436 场周赛 |
| 3449 | [最大化游戏分数的最小值](/solution/3400-3499/3449.Maximize%20the%20Minimum%20Game%20Score/README.md) | | 困难 | 第 436 场周赛 |
| 3450 | [一张长椅的上最多学生](/solution/3400-3499/3450.Maximum%20Students%20on%20a%20Single%20Bench/README.md) | | 简单 | 🔒 |
| 3451 | [Find Invalid IP Addresses](/solution/3400-3499/3451.Find%20Invalid%20IP%20Addresses/README.md) | | 困难 | |

## 版权

Expand Down
Loading
Loading