二维点的天际线——分而治之算法
Skyline of 2D points-Divide and conquer algorithm
我正在做一个项目,我必须找到不被集中的任何其他点支配的点的天际线。如果 x1<=x2 && y1<=y2,则点 A(x1,y1) 支配点 B(x2,y2)。 Here'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 值(升序)排序
好的,我明白逻辑错误了。它在这里:
for (int i=0;i<rightSkylinePoints.size();i++){
if (rightSkylinePoints.get(i).y>=minY){
rightSkylinePoints.remove(i);
当你删除一个点时,其余的点向左移动(据我理解remove
意义),所以下一个(non-treated还)项目获得当前索引i并被排除在外进一步治疗。
最简单的解决方案 - 使用 while
循环并在删除发生时省略递增索引。
另一种方法 - 从较大的索引到较低的索引循环(似乎这样的方向不应该破坏算法)
for (int i=rightSkylinePoints.size() -1; i >=0; i--)
我正在做一个项目,我必须找到不被集中的任何其他点支配的点的天际线。如果 x1<=x2 && y1<=y2,则点 A(x1,y1) 支配点 B(x2,y2)。 Here'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 值(升序)排序
好的,我明白逻辑错误了。它在这里:
for (int i=0;i<rightSkylinePoints.size();i++){
if (rightSkylinePoints.get(i).y>=minY){
rightSkylinePoints.remove(i);
当你删除一个点时,其余的点向左移动(据我理解remove
意义),所以下一个(non-treated还)项目获得当前索引i并被排除在外进一步治疗。
最简单的解决方案 - 使用 while
循环并在删除发生时省略递增索引。
另一种方法 - 从较大的索引到较低的索引循环(似乎这样的方向不应该破坏算法)
for (int i=rightSkylinePoints.size() -1; i >=0; i--)