391 · 数飞机

lintcode

/**
 * Definition of Interval:
 * class Interval {
 * public:
 *     int start, end;
 *     Interval(int start, int end) {
 *         this->start = start;
 *         this->end = end;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param airplanes: An interval array
     * @return: Count of airplanes are in the sky.
     */
    int countOfAirplanes(vector<Interval> &airplanes) {
        // write your code here
        int n = airplanes.size();
        vector<pair<int,int>> lines;
        for(auto airplane : airplanes) {
            lines.emplace_back(make_pair(airplane.start, 1));   // 开始为1
            lines.emplace_back(make_pair(airplane.end, -1));    // 结束为-1
        }
        sort(lines.begin(), lines.end(), [&](pair<int,int> p1, pair<int,int> p2) {
		    if(p1.first != p2.first) return p1.first < p2.first;
            return p1.second < p2.second;
	    });
        // 进行扫描
        int cnt = 0;
        int res = 0;
        for(auto line : lines) {
            cnt += line.second;
            res = max(res, cnt);
        }
        return res;
    }
};

252.会议室 Plus会员题

leetcode
给定一个会议时间安排的数组,每个会议时间都会包括开始和结束的时间扫描线_i++,请你判断一个人是否能够参加这里面的全部会议。

示例 1:
输入: [[0,30],[5,10],[15,20]]
输出: false

示例 2:
输入: [[7,10],[2,4]]
输出: true
class Solution {	//C++
public:
    bool canAttendMeetings(vector<vector<int>>& intervals) {
    	sort(intervals.begin(), intervals.end(),[&](auto a, auto b){
    		return a[0] < b[0];
    	});
    	for(int i = 1; i < intervals.size(); ++i)
    	{
    		if(intervals[i-1][1] > intervals[i][0])
    			return false;
    	}
    	return true;
    }
};

思路:按开会时间排序;然后保证后一个开会开始时间晚于前一个开会的结束时间。

253.会议室II Plus会员题

leetcode
给定一个会议时间安排的数组,每个会议时间都会包括开始和结束的时间扫描线_数组_02
为避免会议冲突,同时要考虑充分利用会议室资源,请你计算至少需要多少间会议室,才能满足这些会议安排。

示例 1:
输入: [[0, 30],[5, 10],[15, 20]]
输出: 2

示例 2:
输入: [[7,10],[2,4]]
输出: 1

思路:直接参考数飞机。

public class Solution {
    public int minMeetingRooms(int[][] intervals) {
        int[] starts = new int[intervals.length], ends = new int[intervals.length];
        for (int i = 0; i < intervals.length; i++) {
            starts[i] = intervals[i][0];
            ends[i] = intervals[i][1];
        }
        Arrays.sort(starts);
        Arrays.sort(ends);
        int room = 0, end = 0;
        for (int i = 0; i < starts.length; i++) {
            if (starts[i] < ends[end]) room++;
            else end++;
        }
        return room;
    }
}

56. 合并区间

leetcode

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(), intervals.end());
        vector<vector<int>> res{{intervals[0][0],intervals[0][1]}};
        int idx = 0;
        for (int i = 1; i < intervals.size(); ++i) {
            if (intervals[i][0] <= res[idx][1]) {
                res[idx][0] = min(res[idx][0], intervals[i][0]);
                res[idx][1] = max(res[idx][1], intervals[i][1]);
            } else {
                res.emplace_back(intervals[i]);
                idx++;
            }
        }
        return res;
    }
};

对二维vector的自定义排序:

sort(intervals.begin(), intervals.end(), [&](vector<int> x, vector<int> y) {
    if (x[0] != y[1]) return x[0] < x[0];
    else return x[1] < x[1];
});

事实上,sort对vector可以进行二维排序,且效率比自己写的自定义排序效率高多了。

// 官方写法,按第二个元素降序
sort(intervals.begin(), intervals.end(), [](const auto& u, const auto& v) {
	return u[1] < v[1];
});

57. 插入区间

leetcode
「手画图解」57. 插入区间 | 分成 3 个阶段考察 这个题解真的非常优秀!!!

class Solution {
public:
    vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
        // 三种情况 最左侧,最右侧,中间部分(考虑合并)
        int n = intervals.size();
        int i = 0;
        vector<vector<int>> res;
        while (i < n && intervals[i][1] < newInterval[0]) {
            res.emplace_back(intervals[i]);
            i++;
        }
        while (i < n && intervals[i][0] <= newInterval[1]) {    // 求重叠的都地方
            newInterval[0] = min(intervals[i][0], newInterval[0]);
            newInterval[1] = max(intervals[i][1], newInterval[1]);
            i++;
        }
        res.emplace_back(newInterval);  // 此处考虑到了intervals为空的情况
        while (i < n && intervals[i][0] > newInterval[1]) { // 不需要判断也可以
            res.emplace_back(intervals[i]);
            i++;
        }
        return res;
    }
};

1272,.删除区间

leetcode
给你一个 有序的 不相交区间列表 intervals 和一个要删除的区间 toBeRemoved, intervals 中的每一个区间 intervals[i] = [a, b] 都表示满足 a <= x < b 的所有实数 x 的集合。

我们将 intervals 中任意区间与 toBeRemoved 有交集的部分都删除。

返回删除所有交集区间后, intervals 剩余部分的 有序 列表。

示例 1:
输入:intervals = [[0,2],[3,4],[5,7]], toBeRemoved = [1,6]
输出:[[0,1],[6,7]]

示例 2:
输入:intervals = [[0,5]], toBeRemoved = [2,3]
输出:[[0,2],[3,5]]

提示:
扫描线_数组_03
扫描线_算法_04

// 自己的代码,没办法验证是否正确
class Solution {
public:
    vector<vector<int>> removeInterval(vector<vector<int>>& intervals, vector<int>& toBeRemoved) {
        // 三种情况 最左侧,最右侧,中间部分(考虑合并)
        int n = intervals.size();
        int i = 0;
        vector<vector<int>> res;
        while (i < n && intervals[i][1] < toBeRemoved[0]) {
            res.emplace_back(intervals[i]);
            i++;
        }
        while(i < n && intervals[i][0] <= toBeRemoved[1]) {
            if (intervals[i][0] < toBeRemoved[0]) {
                res.emplace_back(vector<int> {intervals[i][0], toBeRemoved[0]});
            }
            toBeRemoved[0] = min(intervals[i][1], toBeRemoved[1]);
            toBeRemoved[1] = max(intervals[i][1], toBeRemoved[1]);
            i++;
        }
        if (toBeRemoved[1] - toBeRemoved[0] > 0)
        	res.emplace_back(toBeRemoved);
        if (toBeRemoved[1] < intervals[i-1][1])
            res.emplace_back(vector<int> {toBeRemoved[1], intervals[i - 1][1]});
        while (i < n) {
            res.emplace_back(intervals[i]);
            i++;
        } 
        return res;
    }
};

435. 无重叠区间

leetcode
如果一天只有24小时,从0点开始,有无数美女需要约会,那么罗志祥一定先会选最早结束的, 选最早结束的这意味着完成任务后这一天仍有的时间(剩下的时间)是最多的。
举个例子[26],[1,7],[6,121][3,91]如果你选了[2,6]你今天还剩下18个小时,如果你选了[1,7]你今天就只有17个小时了。

class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        int n = intervals.size();
        sort(intervals.begin(), intervals.end(), [](const auto& u, const auto& v) {
            return u[1] < v[1];
        });
        int end = intervals[0][1]; // 最早结束之间
        int ans = 1;
        for (int i = 1; i < n; ++i) {
            if (intervals[i][0] >= end) {
                ans++;
                end = intervals[i][1];
            }
        }
        return n - ans;
    }
};

1288. 删除被覆盖区间

leetcode

class Solution {
public:
    int removeCoveredIntervals(vector<vector<int>>& intervals) {
        // 不好确定排序规则:先按第一元素升序排序,第二元素降序排序,确保前面的覆盖后面的
        // 转换为无重叠区间
        int n = intervals.size();
        sort(intervals.begin(), intervals.end(), [](const auto& u, const auto& v) {
            if (u[0] != v[0]) return u[0] < v[0];
            else return u[1] > v[1];
        });
        int res = 1;
        int end = intervals[0][1];
        for (int i = 1; i < n; ++i) {
            if (intervals[i][1] > end) {
                end = intervals[i][1];
                res++;
            }
        }
        return res;
    }
};

352. 将数据流变为多个不相交区间

leetcode

1229. 安排会议日程 Plus会员题

leetcode
你是一名行政助理,手里有两位客户的空闲时间表:slots1 和 slots2,以及会议的预计持续时间 duration,请你为他们安排合适的会议时间。

「会议时间」是两位客户都有空参加,并且持续时间能够满足预计时间 duration 的 最早的时间间隔。

如果没有满足要求的会议时间,就请返回一个 空数组。

「空闲时间」的格式是 [start, end],由开始时间 start 和结束时间 end 组成,表示从 start 开始,到 end 结束。

题目保证数据有效:同一个人的空闲时间不会出现交叠的情况,也就是说,对于同一个人的两个空闲时间 [start1, end1] 和 [start2, end2],要么 start1 > end2,要么 start2 > end1。

示例 1:
输入:slots1 = [[10,50],[60,120],[140,210]], 
slots2 = [[0,15],[60,70]], duration = 8
输出:[60,68]

示例 2:
输入:slots1 = [[10,50],[60,120],[140,210]], 
slots2 = [[0,15],[60,70]], duration = 12
输出:[]
 
提示:
1 <= slots1.length, slots2.length <= 10^4
slots1[i].length, slots2[i].length == 2
slots1[i][0] < slots1[i][1]
slots2[i][0] < slots2[i][1]
0 <= slots1[i][j], slots2[i][j] <= 10^9
1 <= duration <= 10^6

986. 区间列表的交集

leetcode

759. 员工空闲时间 Plus会员题

leetcode
给定员工的 schedule 列表,表示每个员工的工作时间

每个员工都有一个非重叠的时间段 Intervals 列表,这些时间段已经排好序

返回表示 所有 员工的 共同,正数长度的空闲时间 的有限时间段的列表,同样需要排好序。

示例 1:
输入:schedule = [[[1,2],[5,6]],[[1,3]],[[4,10]]]
输出:[[3,4]]
解释:
共有 3 个员工,并且所有共同的
空间时间段是 [-inf, 1], [3, 4], [10, inf]。
我们去除所有包含 inf 的时间段,因为它们不是有限的时间段。
 
示例 2:
输入:schedule = [[[1,3],[6,7]],[[2,4]],[[2,5],[9,12]]]
输出:[[5,6],[7,9]]
 

而且,答案中不包含 [5, 5] ,因为长度为 0。
schedule 和 schedule[i] 为长度范围在 [1, 50]的列表。
0 <= schedule[i].start < schedule[i].end <= 10^8。

218. 天际线问题

leetcode

链接

【AgOHの算法胡扯】扫描线算法

基础算法(一) – 扫描线