You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Maximum Disc Coverage实现报错:无法找到findMaxDiscCoverage(java.util.List<Point>)方法求助

解决编译错误及逻辑问题的完整方案

咱们一步步来拆解问题,先搞定编译报错,再修正逻辑上的坑:

一、直接导致编译错误的原因

1. 方法必须归属类

Java不允许在类外面定义方法,你写的createUnitCircle和findMaxDiscCoverage现在是游离在所有类之外的,编译器根本找不到它们。得把这俩方法放到一个类里,比如专门整个工具类DiscCoverageUtils。

2. 方法返回值不完整

如果输入的点列表只有1个或者0个点,外层循环根本不会执行,这时候方法没有任何return语句,编译肯定失败。得在方法末尾加个默认的return逻辑。

3. 错误的提前return

你在findMaxDiscCoverage的内层循环里直接写了return maxDiscCoverage;,这会导致程序刚检查完第一对符合条件的点就直接返回,完全跳过了后面所有点对的遍历,逻辑直接崩了,同时也会引发编译路径问题。

二、逻辑错误修复

除了编译问题,代码里还有几个关键逻辑bug,会导致计算结果完全不对:

1. 圆包含点的判断错误

Circle类的containsPoints方法里,判断条件写的是centre.distanceTo(points.get(i)) <= 2,但咱们的圆半径是1啊!正确的判断应该是点到圆心的距离≤1(考虑浮点精度误差,可以写成<= 1.0 + 1e-6,避免浮点计算的小误差导致误判)。

2. 圆心计算的角度错误

Point类的angleTo方法实现完全错了,它现在算的是中点到原点的角度,而咱们需要的是垂直于两点连线的方向角度(因为单位圆的圆心在两点连线的垂直平分线上)。得基于两点的向量重新计算这个角度。

3. 浮点精度处理

当两点距离非常接近2时,dSquare = 1 - Math.pow(mqDistance, 2)可能因为浮点误差变成负数,导致Math.sqrt抛出异常,得先判断修正这个值。

4. 单点边界情况

当输入只有一个点时,最大覆盖数应该是1(以这个点为圆心的单位圆肯定包含它自己),你的代码没处理这种情况。

5. 遗漏另一个可能的单位圆

给定两个距离≤2的点,其实有两个不同的单位圆能同时包含它们(垂直平分线的两个方向),这两个圆的覆盖点数可能不一样,得都算一遍。

三、修复后的完整代码

class Point {
    private final double x;
    private final double y;
    static final double EPS = 1e-6; // 浮点误差容忍值

    Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    Point midPoint(Point q) {
        return new Point((this.x + q.x) / 2, (this.y + q.y) / 2);
    }

    double distanceTo(Point q) {
        return Math.sqrt(Math.pow(this.x - q.x, 2) + Math.pow(this.y - q.y, 2));
    }

    // 计算垂直于当前点到目标点连线的方向角度
    double perpendicularAngleTo(Point q) {
        double dx = q.x - this.x;
        double dy = q.y - this.y;
        // 垂直方向的向量是(-dy, dx),对应角度为原向量角度+90度
        return Math.atan2(dy, dx) + Math.PI / 2;
    }

    Point moveTo(double theta, double d) {
        return new Point(this.x + d * Math.cos(theta), this.y + d * Math.sin(theta));
    }

    @Override
    public String toString() {
        return "point (" + String.format("%.3f", this.x) + ", " + String.format("%.3f", this.y) + ")";
    }
}

class Circle {
    private final Point centre;
    private final double radius;

    Circle(Point centre, double radius) {
        this.centre = centre;
        this.radius = radius;
    }

    public int containsPoints(List<Point> points) {
        int numOfPoints = 0;
        for (Point p : points) {
            // 考虑浮点误差,判断点到圆心距离是否≤半径
            if (centre.distanceTo(p) <= radius + Point.EPS) {
                numOfPoints++;
            }
        }
        return numOfPoints;
    }

    @Override
    public String toString() {
        return "circle of radius " + this.radius + " centered at " + this.centre;
    }
}

import java.util.List;

public class DiscCoverageUtils {

    public static Circle createUnitCircle(Point p, Point q, boolean isPositiveDirection) {
        double pqDistance = p.distanceTo(q);
        Point midPoint = p.midPoint(q);
        double halfDistance = pqDistance / 2;

        // 处理浮点精度,避免根号下出现负数
        double dSquare = 1 - Math.pow(halfDistance, 2);
        if (dSquare < 0) {
            dSquare = 0;
        }
        double d = Math.sqrt(dSquare);

        // 获取垂直方向角度,支持两个方向
        double theta = p.perpendicularAngleTo(q);
        if (!isPositiveDirection) {
            theta -= Math.PI;
        }
        Point centre = midPoint.moveTo(theta, d);
        return new Circle(centre, 1);
    }

    public static int findMaxDiscCoverage(List<Point> points) {
        // 处理单点或空列表的边界情况
        if (points.size() <= 1) {
            return points.size();
        }

        int maxDiscCoverage = 1; // 至少能包含一个点
        int numOfPoints = points.size();

        for (int i = 0; i < numOfPoints; i++) {
            for (int j = i + 1; j < numOfPoints; j++) {
                Point point1 = points.get(i);
                Point point2 = points.get(j);

                // 两点距离超过2,无法构造同时包含它们的单位圆
                if (point1.distanceTo(point2) > 2 + Point.EPS) {
                    continue;
                }

                // 构造两个方向的单位圆,分别计算覆盖点数
                Circle c1 = createUnitCircle(point1, point2, true);
                int count1 = c1.containsPoints(points);

                Circle c2 = createUnitCircle(point1, point2, false);
                int count2 = c2.containsPoints(points);

                // 更新最大覆盖数
                maxDiscCoverage = Math.max(maxDiscCoverage, Math.max(count1, count2));
            }
        }

        return maxDiscCoverage;
    }
}

四、使用示例

现在你可以这样调用方法:

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Point> points = new ArrayList<>();
        points.add(new Point(0, 0));
        points.add(new Point(1, 0));
        points.add(new Point(0, 1));

        int maxCoverage = DiscCoverageUtils.findMaxDiscCoverage(points);
        System.out.println("最大覆盖点数:" + maxCoverage); // 输出3
    }
}

内容的提问来源于stack exchange,提问作者nicetomeetyou98

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 11:32:41