最大线段重合问题(用堆实现)

简介: 最大线段重合问题(用堆实现)

题目

给定很多线段,每个线段都有两个数[start, end],表示线段开始位置和结束位置,左右都是闭区间。
规定:
1)线段的开始和结束位置一定都是整数值
2)线段重合区域的长度必须>=1
返回线段最多重合区域中,包含了几条线段

认真分析题目,可以发现任何一个重合区域的左边界 必定是某个线段的左边界

题解步骤:
1.把所有线段根据开始位置从小到大排好序
2.遍历所有线段,在小根堆中弹出所有<=开始位置的值
3.把线段的结束位置加入到小根堆中
4.小根堆中有几个数,就是这个线段的答案
5.返回所有线段中答案的最大值

所有线段根据开始位置从小大到大排好序这一步,我们不必自己写排序,可以用比较器,,

代码:

package com.harrison.class04;

import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.PriorityQueue;

/**
 * @author Harrison
 * @create 2022-03-02-21:17
 * @motto 众里寻他千百度,蓦然回首,那人却在灯火阑珊处。
 */
public class Code06_MaxCover {
    // 1.把所有线段根据开始位置从小到大排好序
    // 2.遍历所有线段,在小根堆中弹出所有<=开始位置的值
    // 3.把线段的结束位置加入到小根堆中
    // 4.小根堆中有几个数,就是这个线段的答案

    //

    public static int maxCover1(int[][] lines){
        int min=Integer.MAX_VALUE;
        int max=Integer.MIN_VALUE;
        for(int i=0; i<lines.length; i++){
            min=Math.min(min,lines[i][0]);
            max=Math.max(max,lines[i][1]);
        }
        int cover=0;
        for(double p=min+0.5; p<max; p+=1){
            int cur=0;
            for(int i=0; i<lines.length; i++){
                if(p>lines[i][0] && p<lines[i][1]){
                    cur++;
                }
            }
            cover=Math.max(cover,cur);
        }
        return cover;
    }

    public static int maxCover2(int[][] m){
        Line[] lines=new Line[m.length];
        for(int i=0; i<lines.length; i++){
            lines[i]=new Line(m[i][0],m[i][1]);
        }
        Arrays.sort(lines,new StartComparator());
        PriorityQueue<Integer> heap=new PriorityQueue<>();
        int max=0;
        for(int i=0; i<lines.length; i++){
            while(!heap.isEmpty() && heap.peek()<=lines[i].start){
                heap.poll();
            }
            heap.add(lines[i].end);
            max=Math.max(max,heap.size());
        }
        return max;
    }

    public static class Line{
        public int start;
        public int end;

        public Line(int s,int e){
            start=s;
            end=e;
        }
    }

    public static class StartComparator implements Comparator<Line>{
        public int compare(Line l1,Line l2){
            return l1.start-l2.start;
        }
    }

    public static int[][] generateLines(int N,int L,int R){
        int size=(int)(Math.random()*N)+1;
        int[][] ans=new int[size][2];
        for(int i=0; i<ans.length; i++){
            int a=L+(int)(Math.random()*(R-L+1));
            int b=L+(int)(Math.random()*(R-L+1));
            if(a==b){
                b=a+1;
            }
            ans[i][0]= Math.min(a,b);
            ans[i][1]=Math.max(a,b);
        }
        return ans;
    }

    public static void main(String[] args) {
        int N=100;
        int L=0;
        int R=200;
        int testTimes=100000;
        System.out.println("test begin");
        for(int i=0; i<testTimes; i++){
            int[][] lines=generateLines(N,L,R);
            int ans1=maxCover1(lines);
            int ans2=maxCover2(lines);
            if(ans1!=ans2){
                System.out.println("oops");
            }
        }
        System.out.println("test finish");
    }
}
相关文章
|
3月前
|
C++
已知线段上某点与起点的距离,求该点的坐标
已知线段上某点与起点的距离,求该点的坐标
35 1
|
3月前
|
算法 C++
平面中判断线段与矩形是否相交
平面中判断线段与矩形是否相交
35 0
|
3月前
|
算法 C++ Windows
空间射线与三角形相交算法的两种实现
空间射线与三角形相交算法的两种实现
32 0
|
人工智能 算法 BI
【线段树】找最长“白色”线段
【线段树】找最长“白色”线段
66 0
给你n个线段,代表线段的左右端点,问最少删几条线段,使得剩下当中存在一个线段与所有剩下的所有线段都有交集
考虑枚举每一条线段,求以此线段与所有线段都有交集,需要删除的线段数。 那么对于此线段[L,R],右端点小于L的,与它无交集,需要全删掉。同理左端点大于R的线段,也需要都删掉。 那么剩下的问题,就是需要删几个了。
107 0
平面上给定n条线段,找出一个点,使这个点到这n条线段的距离和最小。
题目:平面上给定n条线段,找出一个点,使这个点到这n条线段的距离和最小。 源码如下: 1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 ...
1098 0
|
Go 计算机视觉
寻找轮廓的中点
主要是回答网友提问,同时回顾主要知识。   #include "stdafx.h" #include  #include "opencv2/imgproc.hpp" #include "opencv2/videoio.
1142 0