스캔 라인 알고리즘 요약

하늘에서 비행기의 수

목록 이착륙 항공기, 주어진 시간은 순서  interval . 하늘을 계산하세요 나타냅니다 항공기의 최대 수를하는 동안?

예 1 :

输入: [(1, 10), (2, 3), (5, 8), (4, 7)]
输出: 3
解释: 
第一架飞机在1时刻起飞, 10时刻降落.
第二架飞机在2时刻起飞, 3时刻降落.
第三架飞机在5时刻起飞, 8时刻降落.
第四架飞机在4时刻起飞, 7时刻降落.
在5时刻到6时刻之间, 天空中有三架飞机.

아이디어 : 클래식 주사선 알고리즘 : 이벤트, 모든 앞에 착륙에 따라 정렬 뒤에 벗고도 같을 시간이 지남에 따라 배열, 헤어 졌 같은 간격 이륙 및 착륙, 그리고 마지막으로 다시 청소는 시작, ++ 계산을 만났다 대회의 끝, count--, 최대 값과 다음 마지막으로 중간에 나타났다는 요청의 대상이다.

/**
 * Definition of Interval:
 * public classs Interval {
 *     int start, end;
 *     Interval(int start, int end) {
 *         this.start = start;
 *         this.end = end;
 *     }
 * }
 */

public class Solution {
    /**
     * @param airplanes: An interval array
     * @return: Count of airplanes are in the sky.
     */
    
    private class Node {
        int time;
        int flag; // 1 take off, 0 is landing;
        public Node(int time, int flag) {
            this.time = time;
            this.flag = flag;
        }
    }
    
    private class NodeComparator implements Comparator<Node> {
        @Override
        public int compare(Node a, Node b) {
            if(a.time != b.time) {
                return a.time - b.time;
            } else {
                // 定义1是起飞,0是下降,这样如果按照大小排序,那么就是如果时间相等的情况下:下降的在前面,起飞的在后面。
                return a.flag - b.flag;
            }
        }
    }
     
    public int countOfAirplanes(List<Interval> airplanes) {
        if(airplanes == null || airplanes.size() == 0) {
            return 0;
        }
        int n = airplanes.size();
        Node[] nodes = new Node[n * 2];
        int index = 0;
        for(Interval interval : airplanes) {
            nodes[index++] = new Node(interval.start, 1);
            nodes[index++] = new Node(interval.end, 0);
        }
        
        Arrays.sort(nodes, new NodeComparator());
        int count = 0;
        int maxcount = 0;
        for(int i = 0; i < nodes.length; i++) {
            if(nodes[i].flag == 1) {
                count++;
            } 
            if(nodes[i].flag == 0) {
                count--;
            }
            maxcount = Math.max(count, maxcount);
        }
        return maxcount;
    }
}

회의실 II

회의 시작 시간과 종료 시간을 포함하여 구간 간격의 일련을 감안할 [[s1,e1],[s2,e2],...] (si < ei)필요 회의실의 최소 번호를 찾기 위해.

샘플 1

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

아이디어 : 코드가 같은 위의 제목과 같은 항공기 정확하게.

/**
 * Definition of Interval:
 * public classs Interval {
 *     int start, end;
 *     Interval(int start, int end) {
 *         this.start = start;
 *         this.end = end;
 *     }
 * }
 */

public class Solution {
    /**
     * @param intervals: an array of meeting time intervals
     * @return: the minimum number of conference rooms required
     */
    
    private class Meeting {
        public int time;
        public int flag;
        public Meeting (int time, int flag) {
            this.time = time;
            this.flag = flag; //  define 1 as start, 0 as end;
        }
    } 
    
    private class MeetingComparator implements Comparator<Meeting> {
        @Override
        public int compare(Meeting a, Meeting b) {
            if(a.time != b.time) {
                return a.time - b.time;
            } else {
                return a.flag - b.flag;
            }
        }
    }
     
    public int minMeetingRooms(List<Interval> intervals) {
        if(intervals == null || intervals.size() == 0) {
            return 0;
        }
        int n = intervals.size();
        Meeting[] meetings = new Meeting[n * 2];
        int index = 0;
        for(Interval interval : intervals) {
            meetings[index++] = new Meeting(interval.start, 1);
            meetings[index++] = new Meeting(interval.end, 0);
        }
        
        Arrays.sort(meetings, new MeetingComparator());
        int count = 0;
        int maxcount = 0;
        for(int i = 0; i < meetings.length; i++) {
            if(meetings[i].flag == 1) {
                count++;
            }
            if(meetings[i].flag == 0) {
                count--;
            }
            maxcount = Math.max(maxcount, count);
        }
        return maxcount;
        
    }
}

시간 교차로

두 시간이 시리즈는 온라인 사용자는 각각의 섹션은 사용자의 로그온 지점 시간 기록,이 정렬 x시간과 오프라인 점을 y큰 작은에서, 같은 기간에 온라인으로 두 명의 사용자를 찾아, 당신의 출력의 기간을 . 당신은 간격의 목록을 반환해야

예 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)]
输出:[]
解释:不存在任何时间段,两个用户同时在线。

주의

  • 우리는 온라인 시계열의 길이를 보장합니다  1 <= len <= 1e6.
  • 우리는 온라인 시계열 법적 보장, 즉, 특정 사용자의 온라인 시계열을 위해, 어떤 두 개의 간격으로 교차하지 않습니다.

사고 : 주사선 알고리즘, 임계 값이 변경되면 수집 될 때, 데이터 수집 횟수 = 2이어야 주목된다.

/**
 * Definition of Interval:
 * public classs Interval {
 *     int start, end;
 *     Interval(int start, int end) {
 *         this.start = start;
 *         this.end = end;
 *     }
 * }
 */

public class Solution {
    /**
     * @param seqA: the list of intervals
     * @param seqB: the list of intervals
     * @return: the time periods
     */
    
    private class Node {
        public int time;
        public int flag;
        public Node(int time, int flag) {
            this.time = time;
            this.flag = flag;
        }
    } 
    
    private class NodeComparator implements Comparator<Node> {
        @Override
        public int compare(Node a, Node b) {
            if(a.time != b.time) {
                return a.time - b.time;
            } else {
                return a.flag - b.flag; // define flag 1 is online, 0 is offline;
            }
        }
    }
    
    public List<Interval> timeIntersection(List<Interval> seqA, List<Interval> seqB) {
        List<Interval> result = new ArrayList<Interval>();
        if(seqA == null || seqA.size() == 0 || seqB == null || seqB.size() == 0) {
            return result;
        }
        
        int n = seqA.size();
        int m = seqB.size();
        Node[] nodes = new Node[n * 2 + m * 2];
        int index = 0;
        for(int i = 0; i < n; i++) {
            nodes[index++] = new Node(seqA.get(i).start, 1);
            nodes[index++] = new Node(seqA.get(i).end, 0);
        }
        for(int i = 0; i < m; i++) {
            nodes[index++] = new Node(seqB.get(i).start, 1);
            nodes[index++] = new Node(seqB.get(i).end, 0);
        }
        
        Arrays.sort(nodes, new NodeComparator());
        int count = 0;
        int start = 0;
        int end = 0;
        for(int i = 0; i < nodes.length; i++) {
            if(nodes[i].flag == 1) {
                count++;
                if(count == 2) {
                    start = nodes[i].time;
                }
            }
            if(nodes[i].flag == 0) {
                if(count == 2) { //每次都是阈值发生变化的时候,收集interval;
                    end = nodes[i].time;
                    result.add(new Interval(start, end));
                    start = 0;
                    end = 0;
                }
                count--;
            }
        }
        return result;
    }
}

 아이디어 2 :이 문제는 데이터가 정렬되어 있기 때문에, A와 B는 분류되어 있기 때문에, 다음 건강 경고 방법, 때마다 킥을 사용할 수 병합 배열과 함께.
맥스 (startA, startB) <최소 경우 (ENDA, endB) 간격 첨가 교차가 크고, 또 프리킥을 떠난 A, B 단부를 참조] O (N + M)

데이터 정렬 // 때문에, 다음 스캔 한 데이터를 중첩에 따라서, 최대 값, 최소값 단부 복용 시작
// 개시 <단부 나타내면이 중복인지, 그렇지 않으면, 오버랩 없을 것이다 드로의 작은 단부 반면 이 이탈 인 이상;

/**
 * Definition of Interval:
 * public classs Interval {
 *     int start, end;
 *     Interval(int start, int end) {
 *         this.start = start;
 *         this.end = end;
 *     }
 * }
 */

public class Solution {
    /**
     * @param seqA: the list of intervals
     * @param seqB: the list of intervals
     * @return: the time periods
     */
    public List<Interval> timeIntersection(List<Interval> seqA, List<Interval> seqB) {
        List<Interval> result = new ArrayList<Interval>();
        if(seqA == null || seqA.size() == 0 || seqB == null || seqB.size() == 0) {
            return result;
        }
        
        int aIndex = 0;
        int bIndex = 0;
        
        // 因为数据是sorted,那么就按照overlap来扫描,也就是start取最大值,end取最小值,
        // 如果start< end,表明有overlap,否则不会有overlap,同时end较小的扔掉,较大的留下;
        while(aIndex < seqA.size() && bIndex < seqB.size()) {
            int start = Math.max(seqA.get(aIndex).start, seqB.get(bIndex).start);
            int end = Math.min(seqA.get(aIndex).end, seqB.get(bIndex).end);
            if(start < end) {
                result.add(new Interval(start, end));
            }
            if(seqA.get(aIndex).end < seqB.get(bIndex).end) {
                aIndex++;
            } else {
                bIndex++;
            }
        }
        return result;
    }
}

수평면  N  타워 각 건물 그것은 트리플로 표현 될 수 있고, 매트릭스 형상 인  (start, end, height)시작 시점, 종점 및 X 축 높이를 표현한다. 건물 사이의 거리를 취득하고 중첩 월부터  N  건물 하우징의 외부 형상.

여러 트리플렛의 외형의 표현이 프로파일은 종단의 위치 및 높이의 개시 위치를 나타내는 세 개의 숫자 (시작, 끝, 높이)를 각각 포함하는 삼중.

샘플 1

输入:
[
    [1, 3, 3],
    [2, 4, 4],
    [5, 6, 1]
]
输出:
[
    [1, 2, 3],
    [2, 4, 4],
    [5, 6, 1]
]

아이디어 : 스캔 라인 알고리즘; 참고 : 정렬, 정렬에 시간은 다음 x는 계산을 사용하지 않는 경우에만 크고 작은 계산, 동일 백업하는 경우, 전면에 큰 만들기 위해, 앞서 착륙 역 행의 다음 높이를했다. 또한, PQ는 비어있을 수 있고, 계산에 따라 0을 비우고;

public class Solution {
    /**
     * @param buildings: A list of lists of integers
     * @return: Find the outline of those buildings
     */
    private class Node {
        private int x;
        private int height;
        private int flag;
        public Node (int x, int height, int flag) {
            this.x = x;
            this.height = height;
            this.flag = flag; // define flag = 1, start, flag = 0, end;
        }
    }
    
    private class NodeComparator implements Comparator<Node> {
        @Override
        public int compare(Node a, Node b) {
            if(a.x != b.x) {
                return a.x - b.x;
            } else {
                if(a.flag != b.flag) {
                    return b.flag - a.flag; // 让起飞在前面;
                } else {
                    return b.height - a.height;  
                    // 让高度最大的排前面;这样,同样x的,只考虑最高的;
                }
            }
        }
    }
    
    public List<List<Integer>> buildingOutline(int[][] buildings) {
        List<List<Integer>> lists = new ArrayList<List<Integer>>();
        if(buildings == null || buildings.length == 0 || buildings[0].length == 0) {
            return lists;
        }
        int n = buildings.length;
        Node[] nodes = new Node[n * 2];
        PriorityQueue<Integer> pq = new PriorityQueue<Integer>(n * 2, Collections.reverseOrder());
        int index = 0;
        for(int i = 0; i < n; i++) {
            int start = buildings[i][0];
            int end = buildings[i][1];
            int height = buildings[i][2];
            
            nodes[index++] = new Node(start, height, 1);
            nodes[index++] = new Node(end, height, 0);
        }
        
        Arrays.sort(nodes, new NodeComparator());
        
        int preheight = 0;
        List<Node> candidates = new ArrayList<Node>();
        for(int i = 0; i < nodes.length; i++) {
            if(nodes[i].flag == 1) {
                pq.add(nodes[i].height);
            }
            if(nodes[i].flag == 0) {
                pq.remove(nodes[i].height);
            }
            int curheight = pq.isEmpty() ? 0 : pq.peek(); // 判断pq是否为空;
            if(preheight != curheight) {
                candidates.add(new Node(nodes[i].x, curheight, -1));
                preheight = curheight;
            }
        }
        convertCandiate(candidates, lists);
        return lists;
    }
    
    private void convertCandiate(List<Node> candidates, List<List<Integer>> lists) {
        List<Integer> list = new ArrayList<Integer>();
        for(int i = 0;  i < candidates.size() -1; i++) {
            Node first = candidates.get(i);
            Node second = candidates.get(i+1);
           
            if(first.height == 0 || first.x == second.x) {
                continue;
            } else {
                list.add(first.x);
                list.add(second.x);
                list.add(first.height);
                lists.add(new ArrayList<Integer>(list));
                list = new ArrayList<Integer>();
            }
        }
    }
}

 

게시 된 562 개 원래 기사 · 원의 찬양 (13) · 전망 170 000 +

추천

출처blog.csdn.net/u013325815/article/details/103957911