返回
我的日程安排表 III:线段树(动态开点)运用题
后端
2024-01-22 21:52:44
我的日程安排表 III:线段树(动态开点)运用题
前言
大家好,我是 掘金日新计划 的参与者。在持续创作的第28天,我选择分享一道 LeetCode 题解——732. 我的日程安排表 III。这道题涉及动态规划和线段树的知识,具有一定挑战性。希望我的分享能给大家带来启发。
题目
给你一个数组 events,其中 events[i] = [start_i, end_i] 表示第 i 个会议的起始时间 start_i 和结束时间 end_i (均为整数)。
你需要安排一场会议,让参加这场会议的人员数目最大化。如果两场会议时间部分重叠,那么它们不能同时进行。
返回你可以安排的最大的会议数目。
示例
输入:events = [[1, 2], [2, 3], [3, 4], [1, 5]]
输出:2
输入:events = [[1, 10], [2, 7], [3, 19], [8, 12], [10, 20], [11, 16], [17, 25]]
输出:4
思路分析
这道题可以看作是一个动态规划问题。我们定义 dp[i] 为在考虑前 i 个会议时,能够安排的最大会议数目。为了计算 dp[i],我们需要考虑以下两种情况:
- 不安排第 i 个会议:在这种情况下,dp[i] 等于 dp[i-1]。
- 安排第 i 个会议:在这种情况下,我们需要找到一个最大的 j,使得会议 j 和会议 i 没有重叠。然后,dp[i] 等于 max(dp[i-1], dp[j] + 1)。
为了找到最大的 j,我们可以使用线段树来维护会议的区间。这样,我们可以在 O(log n) 的时间内找到最大的 j。
代码实现
import java.util.Arrays;
public class MyCalendarThree {
private class SegmentTreeNode {
int start;
int end;
int count;
SegmentTreeNode left;
SegmentTreeNode right;
public SegmentTreeNode(int start, int end) {
this.start = start;
this.end = end;
}
}
private SegmentTreeNode root;
public MyCalendarThree() {
}
public int book(int start, int end) {
update(root, start, end - 1);
return query(root);
}
private void update(SegmentTreeNode node, int start, int end) {
if (node == null) {
node = new SegmentTreeNode(start, end);
}
if (start <= node.start && end >= node.end) {
node.count++;
} else {
int mid = (node.start + node.end) / 2;
if (start <= mid) {
update(node.left, start, end);
}
if (end > mid) {
update(node.right, start, end);
}
}
}
private int query(SegmentTreeNode node) {
if (node == null) {
return 0;
}
return Math.max(node.count, Math.max(query(node.left), query(node.right)));
}
public static void main(String[] args) {
MyCalendarThree myCalendarThree = new MyCalendarThree();
int[][] events = {{1, 2}, {2, 3}, {3, 4}, {1, 5}};
for (int[] event : events) {
int maxCount = myCalendarThree.book(event[0], event[1]);
System.out.println("Max count after booking event: " + Arrays.toString(event) + " is " + maxCount);
}
}
}
总结
这道题涉及动态规划和线段树的知识,具有一定挑战性。通过分析题意,我们可以将其转化为一个动态规划问题。使用线段树来维护会议的区间,可以帮助我们在 O(log n) 的时间内找到最大的 j,从而计算出 dp[i]。
希望我的分享能给大家带来启发。如果大家有任何问题,欢迎在评论区留言。