5534. 可見點的最大數目(C++)---極角排序 + 滑動視窗 解題

重劍DS發表於2020-10-04

題目詳情

給你一個點陣列 points 和一個表示角度的整數 angle ,你的位置是 location ,其中 location = [posx, posy] 且 points[i] = [xi, yi] 都表示 X-Y 平面上的整數座標。

最開始,你面向東方進行觀測。你 不能 進行移動改變位置,但可以通過 自轉 調整觀測角度。換句話說,posx 和 posy 不能改變。你的視野範圍的角度用 angle 表示, 這決定了你觀測任意方向時可以多寬。設 d 為逆時針旋轉的度數,那麼你的視野就是角度範圍 [d - angle/2, d + angle/2] 所指示的那片區域。

對於每個點,如果由該點、你的位置以及從你的位置直接向東的方向形成的角度 位於你的視野中 ,那麼你就可以看到它。

同一個座標上可以有多個點。你所在的位置也可能存在一些點,但不管你的怎麼旋轉,總是可以看到這些點。同時,點不會阻礙你看到其他點。

返回你能看到的點的最大數目。

 

示例 1:

輸入:points = [[2,1],[2,2],[3,3]], angle = 90, location = [1,1]
輸出:3
解釋:陰影區域代表你的視野。在你的視野中,所有的點都清晰可見,儘管 [2,2] 和 [3,3]在同一條直線上,你仍然可以看到 [3,3] 。

示例 2:

輸入:points = [[2,1],[2,2],[3,4],[1,1]], angle = 90, location = [1,1]
輸出:4
解釋:在你的視野中,所有的點都清晰可見,包括你所在位置的那個點。

示例 3:

輸入:points = [[0,1],[2,1]], angle = 13, location = [1,1]
輸出:1
解釋:如圖所示,你只能看到兩點之一。

 

提示:

  • 1 <= points.length <= 105
  • points[i].length == 2
  • location.length == 2
  • 0 <= angle < 360
  • 0 <= posx, posy, xi, yi <= 109

     

題目連結


——題目難度:中等


 





程式碼如下

class Solution {
public:
	int visiblePoints(vector<vector<int>>& points, int angle, vector<int>& location) {
		const double PI = 3.14159;
		int x = location[0], y = location[1], same = 0; //same用於統計相同點個數 
		vector<double> v; //用於儲存極角
		for (int i = 0; i < points.size(); i++) {
			int tx = points[i][0], ty = points[i][1];
			if (x == tx && y == ty) {
				same++;
			}
			else {
				v.push_back(atan2(ty - y, tx - x) * 180 / PI);
			}
		}
		sort(v.begin(), v.end());
		int n = v.size(); //真正極角集的個數
		for(int i = 0; i < n; i++) { //將每個極角加 360 後 加到後面
			v.push_back(v[i] + 360);
		}
		
		/*滑動視窗(雙指標)*/
		/*將每個極角加 360 後 加到後面後的滑動視窗*/
		/*相當於L遍歷了一遍極角集*/
		/*相當於r遍歷了兩遍極角集,只是兩遍極角的比較方式有所改變*/
		int r = 0, ans = 1;
		for (int l = 0; l < n; l++) {
			while (r + 1 < v.size() && v[r + 1] - v[l] <= (double)angle) r++;
			ans = max(ans, r - l + 1);
		}

		return ans + same;
	}
};


 

相關文章