zoukankan      html  css  js  c++  java
  • 扫描线算法模板

    391. 数飞机

    中文
    English

    给出飞机的起飞和降落时间的列表,用序列 interval 表示. 请计算出天上同时最多有多少架飞机?

    样例

    Example 1:

    Input: [(1, 10), (2, 3), (5, 8), (4, 7)]
    Output: 3
    Explanation:
    The first airplane takes off at 1 and lands at 10.
    The second ariplane takes off at 2 and lands at 3.
    The third ariplane takes off at 5 and lands at 8.
    The forth ariplane takes off at 4 and lands at 7.
    During 5 to 6, there are three airplanes in the sky.
    

    Example 2:

    Input: [(1, 2), (2, 3), (3, 4)]
    Output: 1
    Explanation: Landing happen before taking off.
    

    注意事项

    如果多架飞机降落和起飞在同一时刻,我们认为降落有优先权。

    下面这个是参考答案:

    将起飞时间和降落时间放到同一个数组中, 标识出是起飞还是降落时间, 然后对数组排序.

    遍历数组即可, 碰到起飞计数器加一, 碰到降落计数器减一. 维护最大值作为答案.

    注意降落优先于起飞.——当心!!!

    精選裡面的Python解答使用的是cmp這個function, 然而這個cmp function在Python 3.x已經不再作為sorted(), list.sort()的參數了 下面提供的版本是依照精選Python解答改過來的,適用於Python3.x版

    def sorter(x, y):
        if x[0] != y[0]:
            return x[0] - y[0]
        return x[1] - y[1]
    
    
    from functools import cmp_to_key
    class Solution:
        
        def countOfAirplanes(self, airplanes):
            times = []
            for airplane in airplanes:
                times.append((airplane.start, 1))
                times.append((airplane.end, -1))
    
            times = sorted(times, key = cmp_to_key(sorter))
    
            count = 0
            max_count = 0
            for time, delta in times:
                count += delta
                max_count = max(max_count, count)
                
            return max_count
    我的答案:
    """
    Definition of Interval.
    class Interval(object):
        def __init__(self, start, end):
            self.start = start
            self.end = end
    """
    
    class Solution:
        """
        @param airplanes: An interval array
        @return: Count of airplanes are in the sky.
        """
        def countOfAirplanes(self, airplanes):
            # write your code here
            lines = []
            START, END = 1, 0
            for p in airplanes:
                lines.append((p.start, START))
                lines.append((p.end, END))
            
            lines.sort()
            
            c = 0
            ans = 0
            for p, flag in lines:
                if flag == START:
                    c += 1
                else:
                    c -= 1
                ans = max(ans, c)
            assert c == 0
            
            return ans
    

     直接排序就好了,因为python3里tuple的比较就是按照先比较第一个,再比较第二个!!!

    >>> (1, 1) > (1, 2)
    False
    >>> (1, 1) < (1, 2)
    True
    >>> (2, 1) < (2, 3)
    True
    >>> (2, 1) > (2, 3)
    False
    >>> (2, 1) == (2, 1)
    True
    

    L = [(‘d’,2),(‘a’,4),(‘b’,3),(‘c’,2)]
    L.sort(key=lambda x:(x[1],x[0])) 先按照数字排序,再按照字母排序
    L
    [(‘c’, 2), (‘d’, 2), (‘b’, 3), (‘a’, 4)]

    919. 会议室 II

    中文
    English

    给定一系列的会议时间间隔intervals,包括起始和结束时间[[s1,e1],[s2,e2],...] (si < ei),找到所需的最小的会议室数量。

    样例

    样例1

    输入: intervals = [(0,30),(5,10),(15,20)]
    输出: 2
    解释:
    需要两个会议室
    会议室1:(0,30)
    会议室2:(5,10),(15,20)
    

    样例2

    输入: intervals = [(2,7)]
    输出: 1
    解释:
    只需要1个会议室就够了
    

    """
    Definition of Interval.
    class Interval(object):
        def __init__(self, start, end):
            self.start = start
            self.end = end
    """
    
    class Solution:
        """
        @param intervals: an array of meeting time intervals
        @return: the minimum number of conference rooms required
        """
        def minMeetingRooms(self, intervals):
            # Write your code here
            lines = []
            S, E = 1, 0
            for i in intervals:
                lines.append((i.start, S))
                lines.append((i.end, E))
            
            lines.sort()
            
            ans = 0
            c = 0
            for t, flag in lines:
                if flag == S:
                    c += 1
                else:
                    c -= 1
                ans = max(ans, c)
            
            assert c == 0
            return ans
    

    描述

    目前有两个用户的有序在线时间序列,每一个区间记录了该用户的登录时间点x和离线时间点y,请找出这两个用户同时在线的时间段,输出的时间段请从小到大排序。你需要返回一个intervals的列表

    样例

    样例 1:

    输入:seqA = [(1,2),(5,100)], seqB = [(1,6)]
    输出:[(1,2),(5,6)]
    解释:在 (1,2), (5,6) 这两个时间段内,两个用户同时在线。
    

    样例 2:

    输入:seqA = [(1,2),(10,15)], seqB = [(3,5),(7,9)]
    输出:[]
    解释:不存在任何时间段,两个用户同时在线。
    

    30行超简单扫描线算法,仍然是遇到start,count++,遇到end,count--,那么intersection就是找出所有时刻(x, x+1),其中x时刻count=2,x+1时刻的count=1

    public class Solution {
        public List<Interval> timeIntersection(List<Interval> seqA, List<Interval> seqB) {
            seqA.addAll(seqB);
            List<Point> points = new ArrayList<>();
            for (Interval interval : seqA) {
                points.add(new Point(interval.start, true));
                points.add(new Point(interval.end, false));
            }
    
            Collections.sort(points, (p1, p2) -> p1.x - p2.x);
    
            int count = 0;
            int start = -1;
            List<Interval> res = new ArrayList<>();
            for (Point p : points) {
                if (p.ifStart) count++;
                else count--;
    
                if (count == 2) start = p.x;
                if (count == 1 && start != -1) {
                    res.add(new Interval(start, p.x));
                    start = -1;
                }
            }
    
            return res;
    	}
    
        class Point {
            int x;
            boolean ifStart;
            public Point(int x, boolean ifStart) {
                this.x = x;
                this.ifStart = ifStart;
            }
        }
    }

    当然,还有双指针解法

    可以用二路归并相似的思路,用两个指针来分别记录两个list的当前扫描位置

    然后分情况讨论

    1. 如果两个区间没有交集, seqAi.start > seqBj.end or seqAi.end < seqBj.start 在这种情况下就将end小的List的指针向前进一

    2. 如果两个区间有交集, 则统计 start 为两个start中大的那个, end 为两个end 中小的那个, 将这个区间放入答案集合, 并且前进end小的那个list的指针

    因为两个list都是按start sorted并且没有Overlap, 所以结果也一定是按相同顺序排序 时间复杂度O(N) N为两个List中相对较短的长度, 空间复杂度 O(1)

    class Solution:
        """
        @param seqA: the list of intervals
        @param seqB: the list of intervals
        @return: the time periods
        """
        def timeIntersection(self, seqA, seqB):
            # Write your code here
                    
            if seqA == None or seqB == None or len(seqA) == None or len(seqB) == None:
                return []
                
            i,j = 0, 0
            ans = []
            while i < len(seqA) and j < len(seqB):
                if seqA[i].start > seqB[j].end:
                    j += 1
                    continue
                elif seqB[j].start > seqA[i].end:
                    i += 1
                    continue
                
                if seqA[i].start <= seqB[j].start:
                    start = seqB[j].start
                elif seqA[i].start > seqB[j].start:
                    start = seqA[i].start
                
                if seqA[i].end <= seqB[j].end:
                    end = seqA[i].end
                    i += 1
                elif seqA[i].end > seqB[j].end:
                    end = seqB[j].end
                    j += 1
                ans.append(Interval(start, end))
            return ans
  • 相关阅读:
    30. 串联所有单词的子串
    206. 反转链表及扩展
    leetcode合并专题(陆续补充)
    剑指 Offer 25. 合并两个排序的链表及扩展
    1371. 每个元音包含偶数次的最长子字符串
    1334. 阈值距离内邻居最少的城市
    1310. 子数组异或查询
    1297. 子串的最大出现次数
    VS2012安装后 VS2010出现fatal error LNK1123: failure during conversion to COFF
    BFS/DFS 模板 代码
  • 原文地址:https://www.cnblogs.com/bonelee/p/14402886.html
Copyright © 2011-2022 走看看