面试题 16.03. 交点
class Solution {
public boolean inLine(double x, double y, double x1, double y1, double x2, double y2) {
if (y >= Math.min(y1, y2) && y <= Math.max(y1, y2) &&
x >= Math.min(x1, x2) && x <= Math.max(x1, x2)) return true;
return false;
}
public double[] intersection(int[] start1, int[] end1, int[] start2, int[] end2) {
int dx1 = start1[0] - end1[0];
int dy1 = start1[1] - end1[1];
int dx2 = start2[0] - end2[0];
int dy2 = start2[1] - end2[1];
if (dx1 == 0 && dx2 != 0) {
double k2 = (double)dy2 / dx2;
double b2 = (double)start2[1] - k2 * start2[0];
double x = start1[0];
double y = k2 * x + b2;
if (inLine(x, y, start1[0], start1[1], end1[0], end1[1]) &&
inLine(x, y, start2[0], start2[1], end2[0], end2[1])) {
return new double[]{x, y};
}
} else if (dx2 == 0 && dx1 != 0) {
double k1 = (double)dy1 / dx1;
double b1 = (double)start1[1] - k1 * start1[0];
double x = start2[0];
double y = k1 * x + b1;
if (inLine(x, y, start1[0], start1[1], end1[0], end1[1]) &&
inLine(x, y, start2[0], start2[1], end2[0], end2[1])) {
return new double[]{x, y};
}
} else if (dx2 == 0 && dx1 == 0) {
if (start1[0] == start2[0]) {
int x = start1[0];
int y1_h, y1_l, y2_h, y2_l;
if (Math.min(start1[1], end1[1]) >= Math.min(start2[1], end2[1])) {
y1_l = Math.min(start1[1], end1[1]);
y1_h = Math.max(start1[1], end1[1]);
y2_l = Math.min(start2[1], end2[1]);
y2_h = Math.max(start2[1], end2[1]);
} else {
y2_l = Math.min(start1[1], end1[1]);
y2_h = Math.max(start1[1], end1[1]);
y1_l = Math.min(start2[1], end2[1]);
y1_h = Math.max(start2[1], end2[1]);
}
if (y1_l <= y2_h) {
return new double[]{x, y1_l};
}
}
} else {
double k1 = (double)dy1 / dx1;
double b1 = (double)start1[1] - k1 * start1[0];
double k2 = (double)dy2 / dx2;
double b2 = (double)start2[1] - k2 * start2[0];
if (k1 == k2) {
if (b1 == b2) {
int y;
int x1_h, x1_l, x2_h, x2_l;
if (Math.min(start1[0], end1[0]) >= Math.min(start2[0], end2[0])) {
x1_l = Math.min(start1[0], end1[0]);
x1_h = Math.max(start1[0], end1[0]);
if (start1[0] < end1[0]) y = start1[1];
else y = end1[1];
x2_l = Math.min(start2[0], end2[0]);
x2_h = Math.max(start2[0], end2[0]);
} else {
x2_l = Math.min(start1[0], end1[0]);
x2_h = Math.max(start1[0], end1[0]);
x1_l = Math.min(start2[0], end2[0]);
x1_h = Math.max(start2[0], end2[0]);
if (start2[0] < end2[0]) y = start2[1];
else y = end2[1];
}
if (x1_l <= x2_h) {
return new double[]{x1_l, y};
}
}
} else {
double x = (b2 - b1) / (k1 - k2);
double y = k1 * x + b1;
if (inLine(x, y, start1[0], start1[1], end1[0], end1[1]) &&
inLine(x, y, start2[0], start2[1], end2[0], end2[1])) {
return new double[]{x, y};
}
}
}
return new double[]{};
}
}
面试题 16.13. 平分正方形
class Solution {
public void swapSquares(int[] square1, int[] square2) {
for (int i = 0; i < 3; i ++) {
int tmp = square1[i];
square1[i] = square2[i];
square2[i] = tmp;
}
}
public double[] cutSquares(int[] square1, int[] square2) {
if (square1[0] > square2[0]) {
swapSquares(square1, square2);
}
double x1 = square1[0] + square1[2] / 2.0;
double y1 = square1[1] + square1[2] / 2.0;
double x2 = square2[0] + square2[2] / 2.0;
double y2 = square2[1] + square2[2] / 2.0;
if (x1 == x2) {
return new double[]{x1, Math.min(square1[1], square2[1]), x2, Math.max(square1[1] + square1[2], square2[1] + square2[2])};
}
double k = (y1 - y2) / (x1 - x2);
double b = y1 - k * x1;
if (Math.abs(k) <= 1) {
x1 = square1[0];
x2 = Math.max(square1[0] + square1[2], square2[0] + square2[2]);
return new double[]{x1, k * x1 + b, x2, k * x2 + b};
} else {
y1 = Math.min(square1[1], square2[1]);
y2 = Math.max(square1[1] + square1[2], square2[1] + square2[2]);
x1 = (y1 - b) / k;
x2 = (y2 - b) / k;
if (x1 < x2) return new double[]{x1, y1, x2, y2};
else return new double[]{x2, y2, x1, y1};
}
}
}
587. 安装栅栏
class Solution {
public double getDis(double x1, double y1, double x2, double y2) {
return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
public int getCrossProduct(int x0, int y0, int x1, int y1, int x2, int y2) { // 叉积
int X1 = x1 - x0;
int Y1 = y1 - y0;
int X2 = x2 - x0;
int Y2 = y2 - y0;
return X1 * Y2 - X2 * Y1; // 小于0, 顺时针
}
public int[][] outerTrees(int[][] points) {
if (points.length <= 3) return points;
int[] sta = new int[points.length];
int top = 0;
int minXId = 0;
for (int i = 1; i < points.length; i ++) {
if (points[i][1] < points[minXId][1]) {
minXId = i;
}
}
int tmp = points[minXId][0];
points[minXId][0] = points[0][0];
points[0][0] = tmp;
tmp = points[minXId][1];
points[minXId][1] = points[0][1];
points[0][1] = tmp;
int[][] a = new int[points.length - 1][2];
System.arraycopy(points, 1, a, 0, points.length - 1);
Arrays.sort(a, new Comparator<int[]>(){
@Override
public int compare(int[] a, int[] b) {
int c = getCrossProduct(points[0][0], points[0][1], a[0], a[1], b[0], b[1]);
if (c < 0) return 1;
if (c > 0) return -1;
if (a[0] < b[0]) return -1;
if (a[0] > b[0]) return 1;
if (a[1] > b[1]) return -1;
if (a[1] < b[1]) return 1;
return 0;
}
});
System.arraycopy(a, 0, points, 1, points.length - 1);
int fro = 0;
for (; fro < points.length; fro ++) {
if (points[fro][0] != points[0][0]) {
break;
}
}
sta[top ++] = 0;
for (int i = fro - 1; i > 0; i --) {
sta[top ++] = i;
}
if (fro == points.length) {
int[][] ans = new int[top][2];
for (int i = 0; i < top; i ++) {
ans[i] = points[sta[i]];
}
return ans;
}
sta[top ++] = fro;
for (int i = fro + 1; i < points.length; i ++) {
while (top >= 2) {
int c = getCrossProduct(
points[sta[top - 2]][0], points[sta[top - 2]][1],
points[sta[top - 1]][0], points[sta[top - 1]][1],
points[i][0], points[i][1]);
if (c < 0) {
top --;
} else {
break;
}
}
sta[top ++] = i;
}
while (top >= 2) {
int c = getCrossProduct(
points[sta[top - 2]][0], points[sta[top - 2]][1],
points[sta[top - 1]][0], points[sta[top - 1]][1],
points[0][0], points[0][1]);
if (c < 0) {
top --;
} else {
break;
}
}
int[][] ans = new int[top][2];
for (int i = 0; i < top; i ++) {
ans[i] = points[sta[i]];
}
return ans;
}
}
1515. 服务中心的最佳位置