问题描述:
给定两个数组arrx和arry,长度都为N。代表二维平面上有N个点,第i个点的x 坐标和y坐标分别为arrx[i]和arry[i],返回求一条直线最多能穿过多少个点?
思想
坐标系中两个点的位置关系可以分为以下几种情况:共点、共X轴、共Y轴、两点连线有些率。我们根据上面情况,依次遍历每一个数组位置上点与数组后面位置上点之间的关系(这是因为我们在每一次遍历代表的含义是:如果通过这个点,最多直线可以通过几个点。所以遍历到数组i位置时,表示通过前面的点的直线穿过的点不是最多,所以可以不进行遍历)。
代码
准备代码
public static int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
在统计斜率时,K代表斜率(x_y)V代表点的个数。
public static int maxPoints1(int[] arrx, int[] arry) {
if (arrx == null || arrx.length == 0 || arry == null || arry.length == 0) {
return 0;
}
if (arrx.length <= 2) {
return arrx.length;
}
//斜率
//k:x_y v:int
HashMap<String, Integer> map = new HashMap<>();
//结果
int res = 0;
for (int i = 0; i < arrx.length; i++) {
map.clear();
map.put("_", 0);
String key = "_";
//共点
int point = 1;
//共x
int xNum = 0;
//共y
int yNum = 0;
int maxKey = 0;
for (int j = i + 1; j < arrx.length; j++) {
int x = arrx[i];
int y = arry[i];
if (x == arrx[j] && y == arry[j]) {
//共点
point++;
} else if (y == arry[j]) {
xNum++;
} else if (x == arrx[j]) {
yNum++;
} else {
//存在斜率
int tempX = arrx[j] - x;
int tempY = arry[j] - y;
int gcd = gcd(tempX, tempY);
int kX = tempX / gcd;
int kY = tempY / gcd;
key = kX + "_" + kY;
if (!map.containsKey(key)) {
map.put(key, 1);
} else {
map.put(key, map.get(key) + 1);
}
maxKey = Math.max(maxKey, map.get(key));
}
}
res = Math.max(res,
Math.max(xNum, Math.max(yNum, maxKey)) + point
);
}
return res;
}
在统计斜率时,使用两个map嵌套,外面的map K表示x V值嵌套一个map K为y V为点的个数。
public static class Point {
public int x;
public int y;
Point() {
x = 0;
y = 0;
}
Point(int a, int b) {
x = a;
y = b;
}
}
public static int maxPoints2(Point[] points) {
if (points == null) {
return 0;
}
if (points.length <= 2) {
return points.length;
}
Map<Integer, Map<Integer, Integer>> map = new HashMap<>();
int result = 0;
for (int i = 0; i < points.length; i++) {
map.clear();
int samePosition = 1;
int sameX = 0;
int sameY = 0;
int line = 0;
for (int j = i + 1; j < points.length; j++) {
int x = points[j].x - points[i].x;
int y = points[j].y - points[i].y;
if (x == 0 && y == 0) {
samePosition++;
} else if (x == 0) {
sameX++;
} else if (y == 0) {
sameY++;
} else {
int gcd = gcd(x, y);
x /= gcd;
y /= gcd;
if (!map.containsKey(x)) {
map.put(x, new HashMap<Integer, Integer>());
}
if (!map.get(x).containsKey(y)) {
map.get(x).put(y, 0);
}
map.get(x).put(y, map.get(x).get(y) + 1);
line = Math.max(line, map.get(x).get(y));
}
}
result = Math.max(result, Math.max(Math.max(sameX, sameY), line) + samePosition);
}
return result;
}
测试代码
public static Point[] ToShift(int[] arrx, int[] arry) {
if (arrx == null || arrx.length == 0 || arry == null || arry.length == 0) {
return null;
}
Point[] res = new Point[arrx.length];
for (int i = 0; i < arrx.length; i++) {
Point temp = new Point(arrx[i], arry[i]);
res[i] = temp;
}
return res;
}
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[maxSize];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) ((maxValue + 1) * Math.random());
}
return arr;
}
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
public static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
int maxSize = 20;
int maxValue = 200;
int testTime = 500000;
System.out.println("test begin!");
for (int i = 0; i < testTime; i++) {
int[] arrX1 = generateRandomArray(maxSize, maxValue);
int[] arrY1 = generateRandomArray(maxSize, maxValue);
int[] arrX2 = copyArray(arrX1);
int[] arrY2 = copyArray(arrY1);
int res1 = maxPoints1(arrX1, arrY1);
Point[] points = ToShift(arrX2, arrY2);
int res2 = maxPoints2(points);
if (res1 != res2) {
System.out.println("Oops!");
printArray(arrX1);
printArray(arrY1);
System.out.println(res1);
System.out.println(res2);
break;
}
}
System.out.println("test end!");
}