Skip to content

Commit 36d3701

Browse files
committed
同一条直线上的最多的点的数量
1 parent 8d6f08e commit 36d3701

File tree

6 files changed

+186
-2
lines changed

6 files changed

+186
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# max-points-on-a-line(同一条直线上的最多的点的数量)
2+
3+
<center>知识点:穷举</center>
4+
5+
6+
## 题目描述
7+
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
8+
9+
10+
给定2D平面上的n个点,找到位于同一直线上的最大点的数量。
11+
12+
13+
## 解题思路
14+
15+
首先明确如何量化"直线"这一概念,最简单的,我们可以固定一个起始点S(Start),然后遍历剩余的所有点,记做E(End),如果有两个E(记做E1和E2),满足$(E1.x-S.x)/(E1.y-S.y)=(E2.x-S.x)/(E2.y-S.y)$,那么就可以确定E2在S与E1确定的直线上,而$(E1.x-S.x)/(E1.y-S.y)$刚好表示的是以E1和S构成的直线的斜率。所以我们就可以得出结论:要确定三个点S、E1、E2是否在同一条直线上即E2在S、E1构成的唯一直线上,只要满足S-E1直线的斜率与S-E2直线的斜率相等即可。
16+
17+
明确了如何判断三个点是否在一条直线之后我们再回过头来看这道题,n个点,找出点数最多的直线上的点的数量。注意,题目中没有说n个点两两都不相同,所以可能出现多个点的x、y相等,这时候应该多计算一个点(重复的点也是点)。我们可以使用两个循环,第一个循环从第一个点开始遍历所有点作为起始点S,第二个循环从起始点的下一个点遍历后面所有的点作为重点E,构建Map存储当前S对应的所有斜率下的最大点值,逻辑如下:
18+
19+
```
20+
maxCount=0;
21+
for indexS from 0 to Length:
22+
Map<斜率,点数量> map
23+
//以indexS对应点为起点的所有直线中点数量的最大值
24+
tempMaxCount=1
25+
//与当前indexS对应点重合的点的数量
26+
commonCount=0
27+
for indexE from indexS+1 to Length:
28+
if point[indexS]==point[indexE]:
29+
//如果两个点重合
30+
commonCount+=1
31+
else :
32+
斜率=求斜率的函数(point[indexS],point[indexE])
33+
//如果当前斜率之前已经被加入Map中,则更新最大点数为原来的点数+1
34+
if(map.containsKey(斜率)){
35+
tempMaxCount=max(tempMaxCount,map.get(斜率)+1)
36+
map.put(斜率,map.get(斜率)+1)
37+
}else{
38+
tempMaxCount=2
39+
map.put(斜率,2)
40+
}
41+
maxCount=max(maxCount,tempMaxCount+commonCount)
42+
return maxCount
43+
44+
```
45+
46+
以上就是完整的逻辑,有几个细节需要注意:
47+
48+
- 斜率的精度
49+
50+
> 不管使用float还是double都会涉及斜率精度取舍的问题,所以这里建议使用字符串保存精度,方法是将两个点x距离和y距离的比值化为最简分数,然后转化为字符串表示
51+
52+
- x距离或y距离为0
53+
54+
> 由于存在两个点在同一条横线或同一条竖线的可能,这是如果还是和化普通分数那样就不可取,比如0/4和0/9化为字符串后不一样,但是其表示的值是一样的,所以这种情况应该单独考虑
55+
56+
完整逻辑请看详细代码。
57+
58+
## 代码
59+
60+
[这里](../src/three/Solution.java)

LeetCode/Doc/计算逆波兰式的值.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
# 计算逆波兰式的值
1+
# 计算逆波兰式的值(evaluate-reverse-polish-notation)
22

33
<center>知识点:栈</center>
44

55

66
## 题目描述
77

8+
Evaluate the value of an arithmetic expression in Reverse Polish Notation.
9+
10+
Valid operators are+,-,*,/. Each operand may be an integer or another expression.
11+
12+
Some examples:
13+
814
计算逆波兰式的值,给定式子中合法的操作符有+、-、*、/,操作数可能是整型或者另一个表达式,比如:
915

1016
> ["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9
444 Bytes
Binary file not shown.
Binary file not shown.

LeetCode/src/three/Solution.java

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package three;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
/**
7+
* @author dmrfcoder
8+
* @date 2019/4/10
9+
*/
10+
class Point {
11+
int x;
12+
int y;
13+
14+
Point() {
15+
x = 0;
16+
y = 0;
17+
}
18+
19+
Point(int a, int b) {
20+
x = a;
21+
y = b;
22+
}
23+
}
24+
25+
public class Solution {
26+
public int maxPoints(Point[] points) {
27+
28+
int length = points.length;
29+
int maxPointCount = 0;
30+
for (int startIndex = 0; startIndex < length; startIndex++) {
31+
Map<String, Integer> maxPointMap = new HashMap<>();
32+
int commonPointCount = 0;
33+
int tempMaxCount = 1;
34+
for (int endIndex = startIndex + 1; endIndex < length; endIndex++) {
35+
int distanceX = points[startIndex].x - points[endIndex].x;
36+
int distanceY = points[startIndex].y - points[endIndex].y;
37+
38+
39+
if (distanceX == 0 && distanceY == 0) {
40+
commonPointCount += 1;
41+
} else {
42+
String curStrDis;
43+
if (distanceX == 0) {
44+
curStrDis = "distanceX";
45+
} else if (distanceY == 0) {
46+
curStrDis = "distanceY";
47+
} else {
48+
int maxCommonDivisor = commonDivisor(distanceX, distanceY);
49+
if (maxCommonDivisor != 0) {
50+
distanceX = distanceX / maxCommonDivisor;
51+
distanceY = distanceY / maxCommonDivisor;
52+
}
53+
54+
int flag = 0;
55+
56+
if (distanceX < 0) {
57+
distanceX = -distanceX;
58+
flag++;
59+
}
60+
if (distanceY < 0) {
61+
distanceY = -distanceY;
62+
flag++;
63+
}
64+
65+
curStrDis = String.valueOf(distanceX) + distanceY;
66+
if (flag == 1) {
67+
curStrDis = "-" + curStrDis;
68+
}
69+
}
70+
71+
if (maxPointMap.containsKey(curStrDis)) {
72+
tempMaxCount = Math.max(tempMaxCount, maxPointMap.get(curStrDis) + 1);
73+
maxPointMap.put(curStrDis, maxPointMap.get(curStrDis) + 1);
74+
} else {
75+
//初始时put进去2,一个点是起始点,另一个点是当前点
76+
maxPointMap.put(curStrDis, 2);
77+
tempMaxCount = Math.max(tempMaxCount, 2);
78+
}
79+
}
80+
}
81+
maxPointCount = Math.max(maxPointCount, tempMaxCount + commonPointCount);
82+
}
83+
84+
return maxPointCount;
85+
}
86+
87+
/**
88+
* 求最大公约数
89+
*
90+
* @param a
91+
* @param b
92+
* @return
93+
*/
94+
public static int commonDivisor(int a, int b) {
95+
a = Math.abs(a);
96+
b = Math.abs(b);
97+
int count = 0;
98+
for (int i = 1; i <= Math.min(a, b); i++) {
99+
if (a % i == 0 && b % i == 0) {
100+
count = i;
101+
}
102+
}
103+
return count;
104+
}
105+
106+
public static void main(String[] args) {
107+
108+
Point point1 = new Point(2, 3);
109+
Point point2 = new Point(3, 3);
110+
Point point3 = new Point(-5, 3);
111+
Point point4 = new Point(9, -25);
112+
Point[] points = {point1, point2, point3};
113+
Solution solution = new Solution();
114+
System.out.println(solution.maxPoints(points));
115+
}
116+
117+
}

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -142,5 +142,6 @@
142142

143143
# LeetCode
144144

145-
- [求解二叉树的最小深度](./LeetCode/Doc/二叉树的最小深度.md)
145+
- [minimum-depth-of-binary-tree(求解二叉树的最小深度)](./LeetCode/Doc/二叉树的最小深度.md)
146+
- [evaluate-reverse-polish-notation(计算逆波兰式的值)](./LeetCode/Doc/计算逆波兰式的值.md)
146147

0 commit comments

Comments
 (0)