几道几何面试题

388 阅读2分钟

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。

平分正方形

题目描述

image.png

题解

这是一道几何题

首先如何使得面积平分呢?根据我们初中学过的知识以正方形的中心旋转得到的直线都可以将正方形的面积平分。

那么使得两个正方形面积平分的线就是这两个中心的连线。但是就和我们之前做数学题一样,这里也要考虑直线垂直的情况。

接着需要分两种情况

  1. 两个中心的x轴的坐标相同

image.png 这种情况是很好得到ans的
2. x轴的坐标不同

image.png 这种情况很多,但是处理方法是一样的,一个正方形只能交两条平行的边,这样就可以通过计算得到交的是那两条边从而得到相交的两个点。这样4个点就得到再进行比较就可以得到答案。

class Solution {
    public double[] cutSquares(int[] square1, int[] square2) {
        int a,b,c,d,l1,l2;
        a=square1[0];
        b=square1[1];
        l1=square1[2];
        c=square2[0];
        d=square2[1];
        l2=square2[2];
        double point1[]=new double[]{a+1.0*l1/2,b+1.0*l1/2};
        double point2[]=new double[]{c+1.0*l2/2,d+1.0*l2/2};
        if(point1[0]==point2[0])return new double[]{point1[0],Math.min(square1[1],square2[1]),point1[0],Math.max(square1[1]+square1[2],square2[1]+square2[2])};
        double k=(point2[1]-point1[1])/(point2[0]-point1[0]);
        double t=point1[1]-point1[0]*k;
        double[] s11;
        double[] s12;
        double temp=a*k+t;
        if(temp>=b&&temp<=b+l1){
            s11=new double[]{a,a*k+t};
            s12=new double[]{a+l1,(a+l1)*k+t};
        }else{
            if(k>0){
                s12=new double[]{(b+l1-t)/k,b+l1};
                s11=new double[]{(b-t)/k,b};
            }else{
                s11=new double[]{(b+l1-t)/k,b+l1};
                s12=new double[]{(b-t)/k,b};
            }

        }
        double s21[];
        double s22[];
        if(c*k+t>=d&&c*k+t<=d+l2){
            s21=new double[]{c,c*k+t};
            s22=new double[]{c+l2,(c+l2)*k+t};
        }else{
            if(k>0){
                s22=new double[]{(d+l2-t)/k,d+l2};
                s21=new double[]{(d-t)/k,d};
            }else{
                s21=new double[]{(d+l2-t)/k,d+l2};
                s22=new double[]{(d-t)/k,d};
            }

        }
        double x1=Math.min(s11[0],s21[0]);
        double x2=Math.max(s12[0],s22[0]);
        return new double[]{x1,x1==s11[0]?s11[1]:s21[1],x2,x2==s12[0]?s12[1]:s22[1]};
    }
}

最佳直线

题目描述

image.png

题解

可以用o(n^2)的时间复杂度求解。

两重循环枚举i,j其中j从i+1开始枚举,相当于枚举每个点的所有直线,而所有的直线可以通过斜率来体现,当斜率存在时这条直线的点的个数+1,这种枚举的方法不会漏掉点,但是可能会重复枚举,所以只需要每次统计一个点就可以了。这样可以保证后面出现的直线如果前面已经出现的话,那么前面已经将所有的点都统计进去了。

import java.awt.*;
import java.util.*;
class Solution {
     int gcd(int a,int b){
         return b==0?a:gcd(b,a%b);
     }
    public int[] bestLine(int[][] points) {
         int maxNum=0;
         int ans[]=new int[2];
        for(int i=0; i<points.length; i++){
            HashMap<Point,Integer> hashMap=new HashMap<>();
            HashMap<Point,int[]> help=new HashMap<>();
            for(int j=i+1; j<points.length; j++){
                int y=points[j][1]-points[i][1];
                int x=points[j][0]-points[i][0];
                int g=gcd(x,y);
                if(g==0)continue;
                if(x==0)y=x;
                Point point=new Point(y/g,x/g);
                if(hashMap.containsKey(point)){
                    hashMap.put(point,hashMap.get(point)+1);
                }else{
                    hashMap.put(point,1);
                    help.put(point,new int[]{i,j});
                }
                if(hashMap.get(point)>maxNum){
                    maxNum=hashMap.get(point);
                    ans=help.get(point);
                }
            }
        }
        return ans;
    }
}