Princeton Algotithms Collinear Points

Princeton Algotithms Collinear Points

普林斯顿大学算法课第 3 次作业“共线点”。

虽然本次作业给出了暴力方法和快速方法,但是不要以为就能拿到很高的分数。

同样地,想要通过,非常简单,只要答案正确就行了,很容易通过。

但是想要拿到高分,还是不容易的。

以下代码获得 100 分,其中需要注意的点我罗列一下,具体可以看代码理解。

注意与 x 轴平行的点,斜率必须返回正 0。

注意这里必须返回正 0,否则 0 带有正负号,会使得平行于 x 轴的排序出错。例如 (0, 5), (1, 5), (2, 5), (3, 5), (4, 5), (5, 5) 以 (1, 5) 为排序时结果是 (1, 5), (2, 5), (3, 5), (4, 5), (5, 5), (0, 5),(0, 5) 到最后了。因此不能直接一减、一除,那样的 0 是有正负号的。

事实上这一点,在 API 文档中已经提示地很清楚了。

Returns the slope between this point and the specified point.
Formally, if the two points are (x0, y0) and (x1, y1), then the slope is (y1 - y0) / (x1 - x0). For completeness, the slope is defined to be +0.0 if the line segment connecting the two points is horizontal; Double.POSITIVE_INFINITY if the line segment is vertical; and Double.NEGATIVE_INFINITY if (x0, y0) and (x1, y1) are equal.
Points array passsed to the constructor can be changed by some other parts of the code while construction is still in progress.

所以进入构造函数以后,先无脑做 copy。

由于是不可变类型,所以构造的时候就可以直接把结果计算好,然后缓存起来,不需要每次调用的时候去算,调用就直接返回缓存的数据就好了。但是注意,必须返回一份拷贝,以保证不可变。

Stores a reference to an externally mutable object in the instance variable ‘points’, exposing the internal representation of the class.

Instead, create a defensive copy of the object referenced by the parameter variable ‘points’ and store that copy in the instance variable ‘points’.

check that data type is immutable by testing whether each method returns the same value, regardless of any intervening operations

如何去重

Let’s say you have 5 points in their natural order a, b, c, d, e. When you have b as the anchor and sort the remaining points by slopeOrder, you want points with the same slope to appear in their natural order (i.e. … a, c, d, e, …).

To avoid adding the subsegment (b, c, d, e), whenever you start seeing a new slope (i.e. at a), you just need to check if b is less than a in terms of natural order – if it is not, it means b is not the first point in that segment, then you know you don’t need to add it.

import java.util.ArrayList;
import java.util.Arrays;
 
public class BruteCollinearPoints {
   
    private final Point[] points;
    private final LineSegment[] cached;
 
    public BruteCollinearPoints(Point[] points) {
   
        if (points == null) {
   
            throw new IllegalArgumentException();
        }
        // Points array passsed to the constructor can be changed by some other parts of the code while construction is still in progress.
        this.points = Arrays.copyOf(points, points.length);
        for (Point point : this.points) {
   
            if (point == null) {
   
                throw new IllegalArgumentException();
            }
        }
        Arrays.sort(this.points);
        for (int i = 0; i < this.points.length; i++) {
   
            if (i > 0 && Double.compare(this.points[i].slopeTo(this.points[i - 1]), Double.NEGATIVE_INFINITY) == 0) {
   
                throw new IllegalArgumentException();
            }
        }
        // Stores a reference to an externally mutable object in the instance variable 'points', exposing the internal representation of the class.
        // Instead, create a defensive copy of the object referenced by the parameter variable 'points' and store that copy in the instance variable 'points'.
        cached = cache();
    }
 
    private LineSegment[] cache() {
   
        ArrayList<LineSegment> list = new ArrayList<>();
        int n = points.length;
        for (int i = 0; i < n; i++) {
   
            for (int j = i + 1; j < n; j++) {
   
                for (int k = j + 1; k < n; k++) {
   
                    for (int m = k + 1; m < n; m++) {
   
                        Point p = points[i];
                        Point q = points[j];
                        Point r = points[k];
                        Point s = points[m];
                        double slope1 = p.slopeTo(q);
                        double slope2 = p.slopeTo(r);
                        double slope3 = p.slopeTo(s);
                        if (Double
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凝神长老

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值