【华为机考E卷】-“构成正方形的数量”题解思路java

算法每一题,成长每一天~

C0E30 构成正方形的数量

真题链接:【持续更新】2024华为 OD 机试E卷 机考真题库清单(全真题库)

思路

在这里插入图片描述

Java

package com.ccr.paper_f;

import javafx.util.Pair;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class C0E30 {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        if (n < 4) {
            System.out.println(0);
            return;
        }

        Point[] points = new Point[n];
        for (int i = 0; i < n; i++) {
            points[i] = new Point(in.nextInt(), in.nextInt());
        }

        // 计算所有可能得到的正方形
        List<Square> squares = new ArrayList<>(n * n / 2);
        for (int i = 0; i < n - 1; i++) {
            for (int j = i + 1; j < n; j++) {
                Pair<Square, Square> pair =
                        getTwoSquaresByTwoPoints(points[i], points[j]);
                squares.add(pair.getKey());
                squares.add(pair.getValue());
            }
        }

        // 四个点都存在
        Set<Point> inputPoints = Arrays.stream(points).collect(Collectors.toSet());
        Predicate<Square> exists = square ->
                inputPoints.contains(square.p1)
                        && inputPoints.contains(square.p2)
                        && inputPoints.contains(square.p3)
                        && inputPoints.contains(square.p4);

        long count = squares.stream()
                            .filter(exists)  // 过滤出存在的正方形
                            .distinct()     // 根据 hashCode + equals 去重
                            .count();

        System.out.println(count);
    }

    /**
     * 坐标点,也表示向量
     */
    public static class Point {
        public int x;
        public int y;

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

        @Override
        public boolean equals(Object obj) {
            if (obj == null) return false;
            if (this == obj) return true;
            if (!(obj instanceof Point)) return false;
            return x == ((Point) obj).x && y == ((Point) obj).y;
        }

        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    }

    /**
     * 正方形
     */
    public static class Square {
        // 四个坐标点,其中2两个已知
        public final Point vector;
        public final Point p1;
        public final Point p2;
        public final Point p3;
        public final Point p4;

        // 中心点,有小数,所以不用Point表示
        public final String centerPoint;
        public final double area; // 面积

        /**
         * 通过两个点,和垂直向量,得到一个正方形
         *
         * @param p1
         * @param p2
         */
        public Square(Point p1, Point p2, Point vector) {
            this.p1 = p1;
            this.p2 = p2;
            this.vector = vector;
            // 根据向量,得出另外两个点坐标
            this.p3 = new Point(p1.x + vector.x, p1.y + vector.y);
            this.p4 = new Point(p2.x + vector.x, p2.y + vector.y);
            // 计算中心点、面积
            this.centerPoint = (p1.x + p4.x) / (double) 2 + "_" + (p1.y + p4.y) / (double) 2; // p1与p4相对
            this.area = Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2);
        }

        @Override
        public boolean equals(Object o) {
            if (o == null) return false;
            if (this == o) return true;
            if (!(o instanceof Square)) return false;
            Square square = (Square) o;
            // 中心点、面积相同,且至少有一个点相同,则认为相等
            return Objects.equals(centerPoint, square.centerPoint)
                    && Objects.equals(area, square.area)
                    && (
                        Objects.equals(p1, square.p1)
                        || Objects.equals(p1, square.p2)
                        || Objects.equals(p1, square.p3)
                        || Objects.equals(p1, square.p4));
        }

        @Override
        public int hashCode() {
            return Objects.hash(centerPoint, area); // hashCode碰撞后,交给equals判断
        }
    }

    /**
     * 通过两个点,得到两个正方形
     *
     * @param p1
     * @param p2
     * @return
     */
    public static Pair<Square, Square> getTwoSquaresByTwoPoints(Point p1, Point p2) {
        Point vector1 = new Point(p1.y - p2.y, p2.x - p1.x); // 垂直向量
        Point vector2 = new Point(-vector1.x, -vector1.y); // 反向垂直向量
        return new Pair<>(new Square(p1, p2, vector1), new Square(p1, p2, vector2));
    }
}

总结

1、这是最先想到的方法,前面分析的时间比较久,比较容易理解,但是代码量偏多。(后面看看如果有更好的方法,再更新 = . =)
2、关键是 构造 PointSquare两个类,定义它们的 equals()hashCode()方法,用于校验重复。

xx:测试

7
0 0
1 2
3 1
2 -1
-1 3
-2 1
2 4

结果:3
在这里插入图片描述


算法要多练多练多练!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值