力扣2054——两个最好的不重叠活动(贪心)

题目描述(中等)

给你一个下标从 0 开始的二维整数数组 events ,其中 events[i] = [startTimei, endTimei, valuei] 。第 i 个活动开始于 startTimei ,结束于 endTimei ,如果你参加这个活动,那么你可以得到价值 valuei 。你 最多 可以参加 两个时间不重叠 活动,使得它们的价值之和 最大 。

请你返回价值之和的 最大值 。

注意,活动的开始时间和结束时间是 包括 在活动时间内的,也就是说,你不能参加两个活动且它们之一的开始时间等于另一个活动的结束时间。更具体的,如果你参加一个活动,且结束时间为 t ,那么下一个活动必须在 t + 1 或之后的时间开始。

示例 1:
在这里插入图片描述
输入:events = [[1,3,2],[4,5,2],[2,4,3]]
输出:4
解释:选择绿色的活动 0 和 1 ,价值之和为 2 + 2 = 4 。

示例 2:
输入:events = [[1,3,2],[4,5,2],[1,5,5]]
输出:5
解释:选择活动 2 ,价值和为 5 。

示例 3:
输入:events = [[1,5,3],[1,5,1],[6,6,5]]
输出:8
解释:选择活动 0 和 2 ,价值之和为 3 + 5 = 8 。

提示:
2 <= events.length <= 105
events[i].length == 3
1 <= startTimei <= endTimei <= 109
1 <= valuei <= 106

思路

op为0,说明开始事件
op为1,说明事件结束
对于开始的事件,更新答案,即已有价值+该事件的价值,代表两个不重叠活动的价值
对于结束的事件,更新已有价值,即只有第一个活动的价值
在排序上,按时间排序,只有事件结束了才会更新计入结束事件的价值

在实现上,用结构体,重载排序符,首先按时间排序,时间相同的,按flag排序,先进行开始事件再进行结束事件

代码

struct Event {
    // 时间戳
    int ts;
    // op = 0 表示事件开始,op = 1 表示事件结束
    int op;
    int val;
    bool operator< (const Event that) const {
        if(this->ts != that.ts) return this->ts < that.ts;
        else return this->op < that.op;
    }
};

class Solution {
public:
    int maxTwoEvents(vector<vector<int>>& events) {
        vector<Event> evs;
        Event tmp;
        for (const auto& event: events) {
            tmp.ts = event[0];
            tmp.op = 0;
            tmp.val = event[2];
            evs.push_back(tmp);
        }
        for (const auto& event: events) {
            tmp.ts = event[1];
            tmp.op = 1;
            tmp.val = event[2];
            evs.push_back(tmp);
        }

        sort(evs.begin(), evs.end());
        
        int ans = 0, bestFirst = 0;
        for (const auto& [ts, op, val]: evs) {
            if (op == 0) {
                ans = max(ans, val + bestFirst);
            }
            else {
                bestFirst = max(bestFirst, val);
            }
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值