[LeetCode] Max Points on a Line

Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.

這題之前想把任意兩點間都練成直線,這樣一共就有N * (N - 1)條直線(如果含重複的點則直線數更少)。然後把直線表示成點斜式,根據斜率和截距進行來分組計數。試了下,發現這樣要麼得自己實現hashCode方法和equals方法,要麼則要使用兩層嵌套的HashMap。而且爲了防止重複計數,必須得先將所有的點都放到一個set裏,然後再看set的大小。實現的時間複雜度爲O(N)。

發現一個更加簡潔的方法是:還是使用兩層循環,外層遍歷所有點,讓其成爲起點,內層遍歷所有除起始點之外的其它點,作爲終點。這樣一來,每一輪外層遍歷,都會共享同一個起始點,這樣的話判斷直線是否相同只用判斷斜率即可。關鍵是,每一次有一個新的起點的時候,都重建一個新的HashMap,可以輕鬆的避免了之前重複計數的可能

這裏需要有兩個特殊點值得注意:

1)如果兩個點在同一垂線上,斜率就設爲無窮大;

2)如果兩點重合,則要專門分開計數,因爲這樣的點可以在任意以其爲起點的直線上。


	public int maxPoints(Point[] points) {
		if (points == null || points.length == 0)
			return 0;

		int maxCnt = 1;
		// select a starting point
		for (int i = 0; i < points.length; i++) {
			Map<Double, Integer> map = new HashMap<Double, Integer>();
			int duplicateCnt = 0; // the # of duplicate points
			int localMaxCnt = 0; // the maximum count for a starting point
			// select an ending point
			for (int j = 0; j < points.length; j++) {
				if (i == j)
					continue;

				if (points[i].x == points[j].x && points[i].y == points[j].y) {
					duplicateCnt++;
				} else {
					double slope;
					if (points[i].x != points[j].x) {
						slope = (double) (points[i].y - points[j].y)
								/ (points[i].x - points[j].x);
					} else {
						slope = Double.MAX_VALUE;
					}

					if (map.containsKey(slope)) {
						int count = map.get(slope) + 1;
						map.put(slope, count);
						localMaxCnt = Math.max(localMaxCnt, count);
					} else {
						map.put(slope, 1);
						localMaxCnt = Math.max(localMaxCnt, 1);
					}
				}
			}
			// add the # of duplicate points and itself
			localMaxCnt += duplicateCnt + 1;
			maxCnt = Math.max(localMaxCnt, maxCnt);
		}

		return maxCnt;
	}

在實現時另外一點需要注意的是:對於每一個起點,不能等遍歷了所有其它點並完全建好HashMap後再遍歷HashMap來找到最大計數,必須在更新HashMap的時候不斷更新最大計數值,否則會超時。這個應該是因爲測試大數據的時候HashMap裏的數據會比較大,需要做類似循環合併的優化。
發佈了60 篇原創文章 · 獲贊 8 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章