4月打卡活动第12天 面试题第16.03题:交点(困难)
- 题目:给定两条线段(表示为起点start = {X1, Y1}和终点end = {X2, Y2}),如果它们有交点,请计算其交点,没有交点则返回空值。
要求浮点型误差不超过10^-6。若有多个交点(线段重叠)则返回 X 值最小的点,X 坐标相同则返回 Y 值最小的点。
- 题解做法:这题也是太烦了。。。
import java.util.Arrays;
public class Solution {
public double[] intersection(int[] start1_, int[] end1_, int[] start2_, int[] end2_) {
Point[] points = checkAndConvertIntoPoint(start1_, end1_, start2_, end2_);
Point start1 = points[0];
Point end1 = points[1];
Point start2 = points[2];
Point end2 = points[3];
Line line1 = new Line(start1, end1);
Line line2 = new Line(start2, end2);
double epslion = 1e-6f;
Point intersection;
if (line1.k == Integer.MAX_VALUE || line2.k == Integer.MAX_VALUE) {
if (line1.k == Integer.MAX_VALUE && line2.k == Integer.MAX_VALUE) {
if (Math.abs(line1.b - line2.b) <= epslion && (isBetween(start1, start2, end1)) || isBetween(start2, start1, end2)) {
if (isBetween(start1, start2, end1)) {
return new double[]{start2.x, start2.y};
} else {
return new double[]{start1.x, start1.y};
}
}
}
if (line1.k == Integer.MAX_VALUE) {
intersection = new Point(line1.b, line1.b * line2.k + line2.b);
} else {
intersection = new Point(line2.b, line2.b * line1.k + line1.b);
}
} else if (Math.abs(line1.k - line2.k) <= epslion) {
if (Math.abs(line1.b - line2.b) <= epslion && isBetween(start1, start2, end1)) {
return new double[]{start2.x, start2.y};
}
return new double[0];
} else {
double x = (line2.b - line1.b) / (line1.k - line2.k);
double y = x * line1.k + line1.b;
intersection = new Point(x, y);
}
if (isBetween(start1, intersection, end1) && isBetween(start2, intersection, end2)) {
return new double[]{intersection.x, intersection.y};
}
return new double[0];
}
private Point[] checkAndConvertIntoPoint(int[] start1_, int[] end1_, int[] start2_, int[] end2_) {
Point start1 = new Point(start1_[0], start1_[1]);
Point end1 = new Point(end1_[0], end1_[1]);
Point start2 = new Point(start2_[0], start2_[1]);
Point end2 = new Point(end2_[0], end2_[1]);
if (start1.x > end1.x) {
swap(start1, end1);
}
if (start2.x > end2.x) {
swap(start2, end2);
}
if (start1.x > start2.x) {
swap(start1, start2);
swap(end1, end2);
}
return new Point[]{start1, end1, start2, end2};
}
private boolean isBetween(double start, double middle, double end) {
if (start > end) {
return end <= middle && middle <= start;
} else {
return start <= middle && middle <= end;
}
}
private boolean isBetween(Point start, Point middle, Point end) {
return isBetween(start.x, middle.x, end.x) && isBetween(start.y, middle.y, end.y);
}
private void swap(Point point1, Point point2) {
double tempX = point1.x;
double tempY = point1.y;
point1.x = point2.x;
point1.y = point2.y;
point2.x = tempX;
point2.y = tempY;
}
private class Line {
private double k;
private double b;
public Line(Point start, Point end) {
double deltaY = end.y - start.y;
double deltaX = end.x - start.x;
if (deltaX == 0) {
k = Integer.MAX_VALUE;
b = end.x;
} else {
k = deltaY / deltaX;
b = end.y - k * end.x;
}
}
}
private class Point {
private double x;
private double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}
public static void main(String[] args) {
int[] start1 = new int[]{0, 0};
int[] end1 = new int[]{0, 6};
int[] start2 = new int[]{0, 1};
int[] end2 = new int[]{0, 5};
Solution solution = new Solution();
double[] res = solution.intersection(start1, end1, start2, end2);
System.out.println(Arrays.toString(res));
}
}
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/intersection-lcci/solution/shi-yong-zhi-xian-xie-jie-shi-fang-cheng-zai-pan-d/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。