Cracking Coding Interview - 16.14 Best Line

Best Line: Given a two-dimensional graph with points on it, find a line which passes the most number of points.

Hints: #491, #520, #529, #563

解法

给你很多点,找一条线能够经过最多的点。

  1. 把点按照x排序
  2. 选第1个点
    1. 选第2个点和第1个点构成线,看经过多少个点
    2. 选第3个点和第1个点构成线,看经过多少个点
    3. 。。。
    4. 选第N个点
  3. 选第2个点
    1. 选第3个点和第2个点构成线,看经过多少个点
    2. 。。。
    3. 选第N个点和第2个点构成线,看经过多少个点
  4. 。。。
  5. 选第N-1个点

代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public class Point {
  private double x;
  private double y;
}

public interface Line {
  boolean isCross(Point point);
}

public class NormalLine implements Line {
  private double slope;
  private double diff;
  public boolean isCross(Point point) {
    return point.x * slope + diff == point.y;
  }
}

public class VerticalLine implements Line {
  private double x;
  public boolean isCross(Point point) {
    return point.x == x;
  }
}

private Line makeLine(Point p1, Point p2) {
  if (p1.x == p2.x) {
    return new VerticalLine(p1.x);
  }
  double slope = (p1.y - p2.y) / (p1.x - p2.x);
  double diff = p1.y - p1.x * slope;
  return new NormalLine(slope, diff);
}

public Line bestLine(Point[] points) {
  int maxCross = 0;
  Line bestLine = null;
  for (int i = 0; i < points.length - 1; i++) {
    for (int j = i + 1; j < points.length; j++) {
      Line line = makeLine(points[i], points[j]);
      currentCross = 2;
      for (int k = j + 1; k < points.length; k++) {
        if (line.isCross(points[k])) {
          currentCross++;
        }
      }
      if (currentCross > maxCross) {
        bestLine = line;
        maxCross = currentCross;
      }
    }
  }
  return bestLine;
}

时间复杂度:

在i层面,总共进行了N - 1次循环

在j层面,每次循环的次数为:N - 1、N - 2、。。。、2、1

在k层面,每次循环的次数为:N - 2,N - 3、。。。、2、1

所以复杂度为O(n3),n为点的数量

解法2

弄一个Line的Map,记录每条Line的经过的点的数量。用两个循环只构造构造Line,遇到重复的Line则给这个Line的计数加1。最后选一个计数最大的Line。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public Line bestLine(Point[] points) {
  Map<Line, Integer> lineCount = new HashMap<>();
  for (int i = 0; i < points.length - 1; i++) {
    for (int j = i + 1; j < points.length; j++) {
      Line line = makeLine(points[i], points[j]);
      Integer count = lineCount.get(line);
      if (count == null) {
        count = 1;
      }
      count++;
      lineCount.put(line, count);
    }
  }
  Line bestLine = null;
  int max = 0;
  for (Map.Entry<Line, Integer> entry : lineCount.entrySet()) {
    Line line = entry.key();
    int count = entry.value();
    if (count > max) {
      max = count;
      bestLine = line;
    }
  }
  return bestLine;
}

时间复杂度:O(N2),N为点的数量

版权

评论