Java实现平面四点及以上共线点组输出的代码修改方案
问题背景
- 核心需求:读取平面内N个点,输出所有包含4个及以上点的共线点组
- 现有实现:已完成两点斜率计算、基于HashMap的共线点最大数量统计功能
- 现存缺陷:原代码仅统计共线点数量,无法提取并输出具体的共线点坐标集合
修改思路
原代码逻辑为固定单个点作为基准点,计算其余点与基准点的斜率,同斜率的点必然和基准点共线。只需调整存储结构、补充去重逻辑即可满足输出需求:
- 将原
HashMap<String, Integer>(斜率→共线点计数)修改为HashMap<String, List<int[]>>(斜率→同斜率点坐标列表),在遍历过程中同步存储点坐标 - 新增集合存储已输出直线的唯一标识,避免同一条直线被多个基准点重复遍历导致重复输出
- 每个基准点遍历完成后,检查各斜率对应的点列表长度,加上基准点、与基准点重合的点后总数≥4时,整理坐标输出
- 保留原有最大共线点计数逻辑,原统计功能不受影响
修改后完整Java代码
import java.util.*; public class app { public static int maxPoints(int[][] points) { int ans = 1; int n = points.length; // 存储已输出直线的唯一标识,避免重复输出 Set<String> printedLines = new HashSet<>(); for (int i = 0; i < n; i++) { HashMap<String, List<int[]>> slopeMap = new HashMap<>(); // 存储和当前基准点重合的所有点 List<int[]> overlapPoints = new ArrayList<>(); overlapPoints.add(points[i]); int max = 0; for (int j = i + 1; j < n; j++) { if (points[i][0] == points[j][0] && points[i][1] == points[j][1]) { overlapPoints.add(points[j]); continue; } int dy = points[j][1] - points[i][1]; int dx = points[j][0] - points[i][0]; int g = gcd(Math.abs(dy), Math.abs(dx)); int num = dy / g; int deno = dx / g; if (num == 0) deno = 1; if (deno == 0) num = 1; if ((num < 0 && deno < 0) || deno < 0) { num *= -1; deno *= -1; } String slopeKey = createString(deno, num); // 将当前点加入对应斜率的点列表 slopeMap.computeIfAbsent(slopeKey, k -> new ArrayList<>()).add(points[j]); max = Math.max(max, slopeMap.get(slopeKey).size()); } // 检查所有斜率对应的点组,满足≥4点则输出 for (Map.Entry<String, List<int[]>> entry : slopeMap.entrySet()) { List<int[]> linePoints = new ArrayList<>(overlapPoints); linePoints.addAll(entry.getValue()); if (linePoints.size() >= 4) { // 点排序后生成唯一标识,用于去重 linePoints.sort((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]); StringBuilder lineId = new StringBuilder(); for (int[] p : linePoints) { lineId.append(p[0]).append(",").append(p[1]).append(";"); } if (printedLines.add(lineId.toString())) { System.out.print("共线点组:"); for (int[] p : linePoints) { System.out.print(Arrays.toString(p) + " "); } System.out.println(); } } } ans = Math.max(ans, overlapPoints.size() + max); } return ans; } public static int gcd(int a, int b) { if (a == 0) return b; if (b == 0) return a; int max = Math.max(a, b); int min = Math.min(a, b); return gcd(max % min, min); } public static String createString(int a, int b) { return Integer.toString(a) + " " + Integer.toString(b); } public static void main(String[] args) { int[][] points = { { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 4 } }; System.out.println("共线点最大数量为: " + maxPoints(points)); } }
示例运行结果
针对代码中自带的测试用例,运行输出如下:
共线点组:[1, 1] [2, 2] [3, 3] [4, 4] 共线点最大数量为: 4
内容的提问来源于stack exchange,提问作者Aziz Mlayel
相关产品推荐
相关产品推荐

