Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在给定的N个点中包含K个点的最小面积正方形_Java_Algorithm - Fatal编程技术网

Java 在给定的N个点中包含K个点的最小面积正方形

Java 在给定的N个点中包含K个点的最小面积正方形,java,algorithm,Java,Algorithm,这个问题是在一次在线测试中问我的。 笛卡尔平面上有N个点。将给出一个整数K。 目的是找到包含至少K个点的正方形(最小值)的面积。 正方形的边应该平行于轴。正方形的顶点应该是整数。位于侧面的任何点都不被视为在正方形内 我只能解K=N(即所有点都位于正方形中) 我的解决办法是—— static int minarea(int[] x, int[] y, int k) { //Find max y int maxVal = Integer.MIN_VALUE; for(

这个问题是在一次在线测试中问我的。 笛卡尔平面上有N个点。将给出一个整数K。 目的是找到包含至少K个点的正方形(最小值)的面积。 正方形的边应该平行于轴。正方形的顶点应该是整数。位于侧面的任何点都不被视为在正方形内

我只能解K=N(即所有点都位于正方形中)

我的解决办法是——

    static int minarea(int[] x, int[] y, int k) {
    //Find max y
    int maxVal = Integer.MIN_VALUE;
    for(int i : y){
        if(i > maxVal){
            maxVal = i;
        }
    }
    //Find min y
    int minVal = Integer.MAX_VALUE;
    for(int i : x){
        if(i < minVal){
            minVal = i;
        }
    }

    int yLength = (maxVal-minVal)+2;

    //Find max x
    maxVal = Integer.MIN_VALUE;
    for(int i : x){
        if(i > maxVal){
            maxVal = i;
        }
    }
    //Find min x
    minVal = Integer.MAX_VALUE;
    for(int i : x){
        if(i < minVal){
            minVal = i;
        }
    }

    int xLength = (maxVal-minVal)+2;
    int sqSide = (yLength > xLength)?yLength:xLength;
    return sqSide*sqSide;

}
static int minarea(int[]x,int[]y,int k){
//找到max y
int maxVal=整数.MIN_值;
for(int i:y){
如果(i>maxVal){
maxVal=i;
}
}
//找到Miny
int minVal=Integer.MAX_值;
for(int i:x){
如果(imaxVal){
maxVal=i;
}
}
//查找最小x
最小值=整数。最大值;
for(int i:x){
如果(iX长)?叶长:X长;
返回sqSide*sqSide;
}

通解的一种方法是在N个点中找到K个点的所有可能组合,并对所有组合应用上述方法,但这并不好。请告知。

可以看出,我们始终可以移动正方形,使其在左边缘和下边缘具有点。我们将遍历正方形左边缘和下边缘的所有组合。 然后我们需要找到正方形的上边缘或右边缘。对于每一点,我们都可以确定它位于什么边缘。例如,如果
point.x-left>point.y-bottom
,则该点将位于正方形的右边缘,生成的区域将是
(point.x-left)^2
。我们需要按正方形的面积对点进行排序:
area=(max(point.x-left,point.y-bottom))^2
并从该排序列表中选择
K
-第个点。它将是最小的正方形,至少包含
K
个点和指定的左下角。这个解决方案的复杂性是
O(n^3)
,这不是很好,但它比迭代
K
点的所有组合要快。我的java解决方案:

静态void initBounds(int[]x,int[]y)
{
minX=x[0];
maxX=x[0];
minY=y[0];
maxY=y[0];
对于(int i=1;imaxX)
maxX=x[i];
if(x[i]maxY)
maxY=y[i];
if(y[i]sx1&&x[i]sy1&&y[i]yDiff){
sx2=maxX+1;
sy2=最大值+侧差;
}否则{
sx2=最大x+侧差;
sy2=maxY+1;
}
面积=(sx2-sx1)*(sx2-sx1);
int p,q,r,s;
int minSize=(int)Math.sqrt(k)+1;
对于(p=sx1;p=minSize;i--){
int count=计算封闭点(x,y,p,q,p+i,q+i);
如果(计数>=k){
长面积=i*i;
if(电流面积<面积)
面积=面积;
}
其他的
打破
}
}
}
返回区;
}

生成所有可能的正方形,其面积(sqrt(k))*(sqrt(k))为所有点的最大边界正方形。正方形的左下角点可以位于边界正方形内的任何位置。考虑了至少容纳k个点所需的最小尺寸平方(sqrt(k))等约束。如果一个正方形包含至少k个点,且面积小于当前最小面积,则更新面积。

看起来Michiel Smid有一篇关于此问题的论文:

提出了一种算法,在平面上给定一组n个点,然后 整数k,2≤ K≤ n、 查找最小封闭轴平行的k点 广场该算法的运行时间为O(n logn+kn log2) k) 并使用O(n) 空间以前解决这个问题最著名的算法是O(k 2n(对数n) 时间和使用O(kn)空间


你可以采取一种统计方法,计算x轴和y轴上每个点的标准偏差,然后去除第一个标准偏差最高的N-K点。你需要找到包含至少
K
点的正方形还是确切地说
K
点的正方形?我真的不记得这个问题了,但至少应该是这样。也会改变这个问题。
static void initBounds(int[] x, int[] y)
    {
        minX = x[0];
        maxX = x[0];
        minY = y[0];
        maxY = y[0];
        for(int i = 1; i < x.length; i++){
            if(x[i] > maxX)
                maxX = x[i];
            if(x[i] < minX)
                minX = x[i];
            if(y[i] > maxY)
                maxY = y[i];
            if(y[i] < minY)
                minY = y[i];
        }
    }

    static int countEnclosingPoints(int[] x, int[] y, int sx1, int sy1, int sx2, int sy2)
    {
        int count = 0;
        for(int i = 0; i < x.length; i++)
        {
            if(x[i] > sx1 && x[i] < sx2 && y[i] > sy1 && y[i] < sy2)
                count++;
        }
        return count;
    }

    static int minX;
    static int minY;
    static int maxX;
    static int maxY;

    static long minarea(int[] x, int[] y, int k) {
        long area = 0;
        initBounds(x, y);
        int xDiff = maxX - minX;
        int yDiff = maxY - minY;

        int sx1 = minX - 1;
        int sy1 = minY - 1;

        int sideDiff = Math.abs(xDiff - yDiff) + 1;

        int sx2; 
        int sy2;

        if(xDiff > yDiff){
            sx2 = maxX + 1;
            sy2 = maxY + sideDiff;
        } else {
            sx2 = maxX + sideDiff;
            sy2 = maxY + 1;
        }
        area = (sx2 - sx1) * (sx2 - sx1);

        int p, q, r, s;
        int minSize = (int) Math.sqrt(k) + 1;
        for(p = sx1; p < sx2 - minSize; p++) {
            for(q = sy1; q < sy2 - minSize; q++) {
                int xd = sx2 - p; int yd = sy2 - q;
                int sd = (xd < yd)? xd : yd;
                for(int i = sd; i >= minSize; i--){
                    int count = countEnclosingPoints(x, y, p, q, p + i, q + i);
                    if(count >= k) {
                        long currArea = i * i;
                        if(currArea < area)
                            area = currArea;
                    }
                    else
                        break;
                }
            }
        }
        return area;
    }