【问题标题】:Skyline of 2D points-Divide and conquer algorithm二维点的天际线-分治算法
【发布时间】:2018-09-11 05:00:23
【问题描述】:

我正在做一个项目,我必须找到不被集合中任何其他点支配的点的天际线。如果 x1Here's an example

这是我的代码:

public static ArrayList<Point> findSkyline(ArrayList<Point> pointsList){
    if (pointsList.size()<=1){
        return pointsList;
    }

    ArrayList<Point> leftSkylinePoints=new ArrayList<>();
    ArrayList<Point> rightSkylinePoints=new ArrayList<>();
    ArrayList<Point> leftPoints=new ArrayList<>();
    ArrayList<Point> rightPoints=new ArrayList<>();

    for (int i=0;i<pointsList.size()/2;i++){
        leftPoints.add(pointsList.get(i));
    }
    for (int i=pointsList.size()/2;i<pointsList.size();i++){
        rightPoints.add(pointsList.get(i));
    }

    leftSkylinePoints=findSkyline(leftPoints);
    rightSkylinePoints=findSkyline(rightPoints);

    int minY=1001;
    for (int i=0;i<leftSkylinePoints.size();i++){
        if (leftSkylinePoints.get(i).y<minY){
            minY=leftSkylinePoints.get(i).y;
        }
    }
    for (int i=0;i<rightSkylinePoints.size();i++){
        if (rightSkylinePoints.get(i).y>=minY){
            rightSkylinePoints.remove(i);
        }
    }

    System.out.println("MINY: "+minY);

    System.out.print("Left: ");
    for (int i=0;i<leftSkylinePoints.size();i++){
        System.out.print("("+leftSkylinePoints.get(i).x+","+leftSkylinePoints.get(i).y+") ");
    }
    System.out.println();
    System.out.print("Right: ");
    for (int i=0;i<rightSkylinePoints.size();i++){
        System.out.print("("+rightSkylinePoints.get(i).x+","+rightSkylinePoints.get(i).y+") ");
    }
    System.out.println();
    System.out.println();


    leftSkylinePoints.addAll(rightSkylinePoints);
    return leftSkylinePoints;
}

These are the results.

如您所见,点 (6,2) 似乎在天际线中,但它不应该是,因为它应该在第二个 for 循环中被删除。有谁知道为什么会这样?谢谢!

*对于更多的点,我得到了更多不应该存在的东西,但现在我想知道这种情况。

**点根据它们的 x 值排序(升序)

【问题讨论】:

  • 你的方法是如何工作的?例如,我没有看到 X 坐标的任何比较
  • 我试图尝试一下并制作了自己的算法,但后来意识到您的问题专门用于使用分而治之的方法。递归让我头疼。如果您只是在 stackoverflow 上搜索“天际线”,就会有很多帮助。
  • 你对一个点如何支配另一个点的定义似乎是错误的。 “如果 x1
  • 另外,您似乎在检查“地平线”,而不是“天际线”。
  • 我忘了提到点是根据它们的 x 值(升序)排序的。我必须用分而治之的算法来解决它,因为我想要 O(nlogn) 复杂度。我的输入中没有相同的点..

标签: java algorithm geometry points divide


【解决方案1】:

好的,我已经理解了逻辑缺陷。在这里:

 for (int i=0;i<rightSkylinePoints.size();i++){
       if (rightSkylinePoints.get(i).y>=minY){
           rightSkylinePoints.remove(i);

当您删除一个点时,其余部分向左移动(据我了解remove 意义),因此下一个(尚未处理的)项目获取当前索引 i 并被排除在进一步处理之外。

最简单的解决方案 - 使用 while 循环并在删除发生时省略递增索引。

另一种方法 - 从较大的索引循环到较低的索引(似乎这样的方向不应该破坏算法)

 for (int i=rightSkylinePoints.size() -1; i >=0; i--)

【讨论】:

  • 你是完全正确的!我忘记了元素移除时的移动,非常感谢!
猜你喜欢
  • 2013-02-05
  • 2011-03-13
  • 2017-08-12
  • 1970-01-01
  • 2013-02-12
  • 2013-10-30
  • 2016-03-11
  • 2015-04-08
  • 2021-05-06
相关资源
最近更新 更多