Skip to content

feat: add solutions to lc problem: No.3263 #3440

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
Aug 22, 2024
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
98 changes: 47 additions & 51 deletions solution/3200-3299/3262.Find Overlapping Shifts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ tags:

<!-- problem:start -->

# [3262. Find Overlapping Shifts 🔒](https://leetcode.cn/problems/find-overlapping-shifts)
# [3262. 查找重叠的班次 🔒](https://leetcode.cn/problems/find-overlapping-shifts)

[English Version](/solution/3200-3299/3262.Find%20Overlapping%20Shifts/README_EN.md)

## 题目描述

<!-- description:start -->

<p>Table: <code>EmployeeShifts</code></p>
<p>表:<code>EmployeeShifts</code></p>

<pre>
+------------------+---------+
Expand All @@ -26,23 +26,24 @@ tags:
| start_time | time |
| end_time | time |
+------------------+---------+
(employee_id, start_time) is the unique key for this table.
This table contains information about the shifts worked by employees, including the start and end times on a specific date.
(employee_id, start_time) 是此表的唯一主键。
这张表包含员工的排班工作,包括特定日期的开始和结束时间。
</pre>

<p>Write a solution to count the number of <strong>overlapping shifts</strong> for each employee. Two shifts are considered overlapping if one shift&rsquo;s <code>end_time</code> is <strong>later than</strong> another shift&rsquo;s <code>start_time</code>.</p>
<p>编写一个解决方案来为每个员工计算&nbsp;<strong>重叠排班</strong>&nbsp;的数量。如果一个排班的&nbsp;<code>end_time</code>&nbsp;比另一个排班的&nbsp;<code>start_time</code>&nbsp;<strong>更晚&nbsp;</strong>则认为两个排班重叠。</p>

<p><em>Return the result table ordered by</em> <code>employee_id</code> <em>in <strong>ascending</strong> order</em>.</p>
<p>返回结果表以&nbsp;<code>employee_id</code> <strong>升序&nbsp;</strong>排序。</p>

<p>The query result format is in the following example.</p>
<p>查询结果格式如下所示。</p>

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

<p><b>示例:</b></p>

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

<p><code>EmployeeShifts</code> table:</p>
<p><code>EmployeeShifts</code> 表:</p>

<pre class="example-io">
+-------------+------------+----------+
Expand All @@ -61,7 +62,7 @@ This table contains information about the shifts worked by employees, including
+-------------+------------+----------+
</pre>

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

<pre class="example-io">
+-------------+--------------------+
Expand All @@ -73,38 +74,38 @@ This table contains information about the shifts worked by employees, including
+-------------+--------------------+
</pre>

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

<ul>
<li>Employee 1 has 3 shifts:
<li>员工 1 3 个排班:
<ul>
<li>08:00:00 to 12:00:00</li>
<li>11:00:00 to 15:00:00</li>
<li>14:00:00 to 18:00:00</li>
<li>08:00:00 12:00:00</li>
<li>11:00:00 15:00:00</li>
<li>14:00:00 18:00:00</li>
</ul>
The first shift overlaps with the second, and the second overlaps with the third, resulting in 2 overlapping shifts.</li>
<li>Employee 2 has 2 shifts:
第一个排班与第二个排班重叠,第二个排班与第三个排班重叠,因此有 2&nbsp;个重叠排班。</li>
<li>员工 2&nbsp;有 2 个排班:
<ul>
<li>09:00:00 to 17:00:00</li>
<li>16:00:00 to 20:00:00</li>
<li>09:00:00 17:00:00</li>
<li>16:00:00 20:00:00</li>
</ul>
These shifts overlap with each other, resulting in 1 overlapping shift.</li>
<li>Employee 3 has 3 shifts:
这些排班彼此重叠,因此有 1 个重叠排班。</li>
<li>员工 3 3 个排班:
<ul>
<li>10:00:00 to 12:00:00</li>
<li>13:00:00 to 15:00:00</li>
<li>16:00:00 to 18:00:00</li>
<li>10:00:00 12:00:00</li>
<li>13:00:00 15:00:00</li>
<li>16:00:00 18:00:00</li>
</ul>
None of these shifts overlap, so Employee 3 is not included in the output.</li>
<li>Employee 4 has 2 shifts:
这些排班没有重叠,所以员工 3 不包含在输出中。</li>
<li>员工 4 2 个排班:
<ul>
<li>08:00:00 to 10:00:00</li>
<li>09:00:00 to 11:00:00</li>
<li>08:00:00 10:00:00</li>
<li>09:00:00 11:00:00</li>
</ul>
These shifts overlap with each other, resulting in 1 overlapping shift.</li>
这些排班彼此重叠,因此有 1 个重叠排班。</li>
</ul>

<p>The output shows the employee_id and the count of overlapping shifts for each employee who has at least one overlapping shift, ordered by employee_id in ascending order.</p>
<p>输出展示了 employee_id 和至少有一个重叠排班的员工的重叠排班的数量,以 employee_id 升序排序。</p>
</div>

<!-- description:end -->
Expand All @@ -117,13 +118,12 @@ This table contains information about the shifts worked by employees, including

我们首先使用自连接,将 `EmployeeShifts` 表连接自身。通过连接条件,确保只比较同一个员工的班次,并且检查班次之间是否存在重叠。

1. `t1.start_time < t2.end_time`:确保第一个班次的开始时间早于第二个班次的结束时间。
1. `t1.start_time < t1.start_time`:确保第一个班次的开始时间早于第二个班次的结束时间。
1. `t1.end_time > t2.start_time`:确保第一个班次的结束时间晚于第二个班次的开始时间。
1. `t1.start_time != t2.start_time`:避免班次与自身比较。

接下来,我们对数据按照 `employee_id` 进行分组,统计每个员工的重叠班次数量。这里我们将重叠班次数量除以 2,因为我们在自连接时,每个重叠的班次都会被计算两次。
接下来,我们对数据按照 `employee_id` 进行分组,统计每个员工的重叠班次数量。

最后,我们筛选出重叠班次数量大于 0 的员工,并按照 `employee_id` 进行升序排序。
最后,我们筛选出重叠班次数量大于 $0$ 的员工,并按照 `employee_id` 进行升序排序。

<!-- tabs:start -->

Expand All @@ -132,14 +132,13 @@ This table contains information about the shifts worked by employees, including
```sql
SELECT
t1.employee_id,
COUNT(*) / 2 AS overlapping_shifts
COUNT(*) AS overlapping_shifts
FROM
EmployeeShifts t1
JOIN EmployeeShifts t2
ON t1.employee_id = t2.employee_id
AND t1.start_time < t2.end_time
AND t1.start_time < t2.start_time
AND t1.end_time > t2.start_time
AND t1.start_time != t2.start_time
GROUP BY 1
HAVING overlapping_shifts > 0
ORDER BY 1;
Expand All @@ -152,23 +151,20 @@ import pandas as pd


def find_overlapping_shifts(employee_shifts: pd.DataFrame) -> pd.DataFrame:
merged = employee_shifts.merge(
employee_shifts, on="employee_id", suffixes=("_1", "_2")
merged_shifts = employee_shifts.merge(
employee_shifts, on="employee_id", suffixes=("_t1", "_t2")
)
overlap = merged[
(merged["start_time_1"] < merged["end_time_2"])
& (merged["end_time_1"] > merged["start_time_2"])
& (merged["start_time_1"] != merged["start_time_2"])
overlapping_shifts = merged_shifts[
(merged_shifts["start_time_t1"] < merged_shifts["start_time_t2"])
& (merged_shifts["end_time_t1"] > merged_shifts["start_time_t2"])
]
overlap_counts = (
overlap.groupby("employee_id").size().reset_index(name="overlapping_shifts")
)
overlap_counts["overlapping_shifts"] = overlap_counts["overlapping_shifts"] // 2
result = (
overlap_counts[overlap_counts["overlapping_shifts"] > 0]
.sort_values("employee_id")
.reset_index(drop=True)
overlapping_shifts.groupby("employee_id")
.size()
.reset_index(name="overlapping_shifts")
)
result = result[result["overlapping_shifts"] > 0]
result = result.sort_values("employee_id").reset_index(drop=True)
return result
```

Expand Down
39 changes: 17 additions & 22 deletions solution/3200-3299/3262.Find Overlapping Shifts/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,16 @@ This table contains information about the shifts worked by employees, including

<!-- solution:start -->

### Solution 1: Self-Join + Group Count
### Solution 1: Self-Join + Group Counting

We start by using a self-join to join the `EmployeeShifts` table with itself. The join condition ensures that only shifts of the same employee are compared, and checks if there is any overlap between the shifts.
We first use a self-join to connect the `EmployeeShifts` table to itself. The join condition ensures that we only compare shifts belonging to the same employee and check if there is any overlap between shifts.

1. `t1.start_time < t2.end_time`: Ensures that the start time of the first shift is earlier than the end time of the second shift.
1. `t1.start_time < t2.start_time`: Ensures that the start time of the first shift is earlier than the start time of the second shift.
2. `t1.end_time > t2.start_time`: Ensures that the end time of the first shift is later than the start time of the second shift.
3. `t1.start_time != t2.start_time`: Avoids comparing a shift with itself.

Next, we group the data by `employee_id` and count the number of overlapping shifts for each employee. We divide the count by 2 because each overlap is counted twice in the self-join.
Next, we group the data by `employee_id` and count the number of overlapping shifts for each employee.

Finally, we filter out employees with an overlapping shift count greater than 0 and sort the results in ascending order by `employee_id`.
Finally, we filter out employees with overlapping shift counts greater than $0$ and sort the results in ascending order by `employee_id`.

<!-- tabs:start -->

Expand All @@ -132,14 +131,13 @@ Finally, we filter out employees with an overlapping shift count greater than 0
```sql
SELECT
t1.employee_id,
COUNT(*) / 2 AS overlapping_shifts
COUNT(*) AS overlapping_shifts
FROM
EmployeeShifts t1
JOIN EmployeeShifts t2
ON t1.employee_id = t2.employee_id
AND t1.start_time < t2.end_time
AND t1.start_time < t2.start_time
AND t1.end_time > t2.start_time
AND t1.start_time != t2.start_time
GROUP BY 1
HAVING overlapping_shifts > 0
ORDER BY 1;
Expand All @@ -152,23 +150,20 @@ import pandas as pd


def find_overlapping_shifts(employee_shifts: pd.DataFrame) -> pd.DataFrame:
merged = employee_shifts.merge(
employee_shifts, on="employee_id", suffixes=("_1", "_2")
merged_shifts = employee_shifts.merge(
employee_shifts, on="employee_id", suffixes=("_t1", "_t2")
)
overlap = merged[
(merged["start_time_1"] < merged["end_time_2"])
& (merged["end_time_1"] > merged["start_time_2"])
& (merged["start_time_1"] != merged["start_time_2"])
overlapping_shifts = merged_shifts[
(merged_shifts["start_time_t1"] < merged_shifts["start_time_t2"])
& (merged_shifts["end_time_t1"] > merged_shifts["start_time_t2"])
]
overlap_counts = (
overlap.groupby("employee_id").size().reset_index(name="overlapping_shifts")
)
overlap_counts["overlapping_shifts"] = overlap_counts["overlapping_shifts"] // 2
result = (
overlap_counts[overlap_counts["overlapping_shifts"] > 0]
.sort_values("employee_id")
.reset_index(drop=True)
overlapping_shifts.groupby("employee_id")
.size()
.reset_index(name="overlapping_shifts")
)
result = result[result["overlapping_shifts"] > 0]
result = result.sort_values("employee_id").reset_index(drop=True)
return result
```

Expand Down
23 changes: 10 additions & 13 deletions solution/3200-3299/3262.Find Overlapping Shifts/Solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,18 @@


def find_overlapping_shifts(employee_shifts: pd.DataFrame) -> pd.DataFrame:
merged = employee_shifts.merge(
employee_shifts, on="employee_id", suffixes=("_1", "_2")
merged_shifts = employee_shifts.merge(
employee_shifts, on="employee_id", suffixes=("_t1", "_t2")
)
overlap = merged[
(merged["start_time_1"] < merged["end_time_2"])
& (merged["end_time_1"] > merged["start_time_2"])
& (merged["start_time_1"] != merged["start_time_2"])
overlapping_shifts = merged_shifts[
(merged_shifts["start_time_t1"] < merged_shifts["start_time_t2"])
& (merged_shifts["end_time_t1"] > merged_shifts["start_time_t2"])
]
overlap_counts = (
overlap.groupby("employee_id").size().reset_index(name="overlapping_shifts")
)
overlap_counts["overlapping_shifts"] = overlap_counts["overlapping_shifts"] // 2
result = (
overlap_counts[overlap_counts["overlapping_shifts"] > 0]
.sort_values("employee_id")
.reset_index(drop=True)
overlapping_shifts.groupby("employee_id")
.size()
.reset_index(name="overlapping_shifts")
)
result = result[result["overlapping_shifts"] > 0]
result = result.sort_values("employee_id").reset_index(drop=True)
return result
5 changes: 2 additions & 3 deletions solution/3200-3299/3262.Find Overlapping Shifts/Solution.sql
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
SELECT
t1.employee_id,
COUNT(*) / 2 AS overlapping_shifts
COUNT(*) AS overlapping_shifts
FROM
EmployeeShifts t1
JOIN EmployeeShifts t2
ON t1.employee_id = t2.employee_id
AND t1.start_time < t2.end_time
AND t1.start_time < t2.start_time
AND t1.end_time > t2.start_time
AND t1.start_time != t2.start_time
GROUP BY 1
HAVING overlapping_shifts > 0
ORDER BY 1;
Loading
Loading