Leetcode 447:Number of Boomerangs
阿新 • • 發佈:2021-02-11
Leetcode 447:Number of Boomerangs
You are given n points in the plane that are all distinct, where points[i] = [xi, yi]. A boomerang is a tuple of points (i, j, k) such that the distance between i and j equals the distance between i and k (the order of the tuple matters).
Return the number of boomerangs.
說人話:
給定平面上 n 對互不相同的點 points ,其中 points[i] = [xi, yi] 。迴旋鏢是由點 (i, j, k) 表示的元組 ,其中 i 和 j 之間的距離和 i 和 k 之間的距離相等(需要考慮元組的順序)。
返回平面上所有迴旋鏢的數量。
幾個要點:
- 點是不同的點
- 點 i 是樞紐
- 返回的是迴旋鏢的數量,不是具體的迴旋鏢
n == points.length
1 <= n <= 500
:說明我們可以接受 O(n2) 級別的演算法points[i].length == 2
- -104 <= xi, yi <= 104
示例:
[法1] 暴力法
思路
- 遍歷所有點的情況
- 三層迴圈,找到符合條件的元組
- 記錄元組個數
程式碼
class Solution {
public int numberOfBoomerangs(int[][] points) {
int result = 0;
//三層遍歷
for(int a=0;a<points.length;a++){
for(int b=0;b<points.length;b++){
for(int c=0;c<points. length;c++){
//A.B.C為三個不同的點
if( a!=b && a!=c && b!=c){
//A.B的距離
int distanceAB =
(points[a][0]-points[b][0])*(points[a][0]-points[b][0])+
(points[a][1]-points[b][1])*(points[a][1]-points[b][1]);
//A.C的距離
int distanceAC =
(points[a][0]-points[c][0])*(points[a][0]-points[c][0])+
(points[a][1]-points[c][1])*(points[a][1]-points[c][1]);
//距離相等則累加
if( distanceAB == distanceAC){
result++;
}
}
}
}
}
return result;
}
}
提交結果
程式碼分析
- 時間複雜度:O(n3)
- 空間複雜度:O(1)
改進思路
因為 N 的級別為 500,所以我們可以接受 n2 的複雜度, n3 就太大了。我們需要想辦法將時間複雜度降為 O(n2) 甚至更低。
[法2] 查詢表靈活選擇鍵值
思路
我們可以發現題目中 點 i
其實是一個樞紐,那麼我們就可以對於每個 點 i
,遍歷其他剩餘點到 點 i 的距離,然後看看相同距離的點有多少個,對這些相同距離的點進行排列組合 An2,就可以了。
整體思路如下:
- 遍歷所有點 i
- 對每一個點 i 記錄其他所有點與點 i 的距離,並記錄相同距離的點的個數
- 對這些相同距離的點進行排列組合 An2
- 累計所有的點 i 得到迴旋鏢的個數
程式碼
class Solution {
public int numberOfBoomerangs(int[][] points) {
int result = 0;
//遍歷每一個點 i
for(int i=0;i<points.length;i++){
Map<Integer,Integer> map = new HashMap<>();
//以 i 作為樞紐
for(int j=0;j<points.length;j++){
//記錄其他點到點 i 的距離
if( i!=j ){
//距離的平方
int distance =
(points[i][0]-points[j][0])*(points[i][0]-points[j][0]) +
(points[i][1]-points[j][1])*(points[i][1]-points[j][1]);
//統計相同記錄的點的個數
Integer count = map.get(distance);
if(count !=null && count>0){
count++;
map.put(distance,count);
}else{
map.put(distance,1);
}
}
}
//對這些相同距離的點進行排列組合
Set<Integer> keys = map.keySet();
for(Integer key: keys){
Integer count = map.get(key);
if(count != null && count >= 2){
result += (count)*(count-1);
}
}
}
return result;
}
}
提交結果
程式碼分析
- 時間複雜度:O(n2)。
- 空間複雜度:因為對於每一個點 i 操作完成後都會釋放 map,然後再申請,所以自始至終都只需要 O(n) 的輔助空間。
陷阱
本題中保證點的座標在 [-10000,10000] 的範圍內,所以算距離的時候不會發生整數溢位。如果沒有這個條件的話,最好算距離的時候轉為 long 或者 decimal 來進行計算,避免整數溢位。