###### tags: `Leetcode` `medium` `graph` `dfs` `union find` `python` `c++`
# 947. Most Stones Removed with Same Row or Column
## [題目連結:] https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/description/
## 題目:
On a 2D plane, we place ```n``` stones at some integer coordinate points. Each coordinate point may have at most one stone.
A stone can be removed if it shares either **the same row or the same column** as another stone that has not been removed.
Given an array ```stones``` of length ```n``` where ```stones[i] = [xi, yi]``` represents the location of the ```ith``` stone, return the largest possible number of stones that can be removed.
**Example 1:**
```
Input: stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]]
Output: 5
Explanation: One way to remove 5 stones is as follows:
1. Remove stone [2,2] because it shares the same row as [2,1].
2. Remove stone [2,1] because it shares the same column as [0,1].
3. Remove stone [1,2] because it shares the same row as [1,0].
4. Remove stone [1,0] because it shares the same column as [0,0].
5. Remove stone [0,1] because it shares the same row as [0,0].
Stone [0,0] cannot be removed since it does not share a row/column with another stone still on the plane.
```
**Example 2:**
```
Input: stones = [[0,0],[0,2],[1,1],[2,0],[2,2]]
Output: 3
Explanation: One way to make 3 moves is as follows:
1. Remove stone [2,2] because it shares the same row as [2,0].
2. Remove stone [2,0] because it shares the same column as [0,0].
3. Remove stone [0,2] because it shares the same row as [0,0].
Stones [0,0] and [1,1] cannot be removed since they do not share a row/column with another stone still on the plane.
```
**Example 3:**
```
Input: stones = [[0,0]]
Output: 0
Explanation: [0,0] is the only stone on the plane, so you cannot remove it.
```
## 解題想法:
* 此題為,給n個石頭的座標,同行or同列的石頭都要移除,求最多移除個數
* 流程:
* 求**連通子圖的個數**,每個連通圖即為1個石頭,剩下的全移除
* Step1:
* 建立graph
* key: position in stones
* value: list[]存相連的位置
* 雙迴圈進行判斷
* 若兩位置的x或y相等,則相連
* Step2:
* visited=[False]* len(stones)
* 紀錄每個位置是否拜訪過
* res=0
* 紀錄連通子圖個數
* Step3:
* 遍歷每個位置 for i in range(len(stones)):
* 對於尚未拜訪的i進行後續Step4操作
* Step4:
* res+=1
* visited[i]=True
* 將鄰居、鄰居的鄰居皆改為True
* que=[i]
* while que判斷
* Step5:
* return 要刪掉的node數=len(stones)-連通子圖個數
## Python:
``` python=
from collections import defaultdict
class Solution(object):
def removeStones(self, stones):
"""
:type stones: List[List[int]]
:rtype: int
"""
#找出連通子圖的個數
graph=defaultdict(list) #key: pos in stones ; value: node which connected
#connect the graph
for pos1, coordinate1 in enumerate(stones):
for pos2 in range(pos1):
coordinate2=stones[pos2]
if coordinate1[0]==coordinate2[0] or coordinate1[1]==coordinate2[1]:
graph[pos1].append(pos2)
graph[pos2].append(pos1)
visited=[False]*len(stones)
res=0 #紀錄連通子圖個數
for i in range(len(stones)):
if not visited[i]: #尚未拜訪
res+=1
visited[i]=True
#鄰居、鄰居的鄰居皆改為False
que=[i]
while que:
curPos=que.pop(0)
for neighber in graph[curPos]:
if not visited[neighber]:
visited[neighber]=True
que.append(neighber)
#return 要刪掉的node數=len(stones)-連通子圖數
return len(stones)-res
```
## C++:
``` cpp=
class Solution {
public:
int removeStones(vector<vector<int>>& stones) {
unordered_map<int, vector<int>> graph;
int n=stones.size();
//connect the graph
for (int pos1=0; pos1<n; pos1++){
for (int pos2=0; pos2<pos1; pos2++){
if (stones[pos1][0]==stones[pos2][0] || stones[pos1][1]==stones[pos2][1]){
graph[pos1].push_back(pos2);
graph[pos2].push_back(pos1);
}
}
}
vector<bool> visited(n,false);
int res=0;
//dfs
for (int i=0; i<n; i++){
if (!visited[i]){
res+=1;
visited[i]=true;
queue<int> que;
que.push(i);
//let visited[neighber]=true
while (!que.empty()){
int curPos=que.front(); que.pop();
for (auto neighber: graph[curPos]){
if (!visited[neighber]){
visited[neighber]=true;
que.push(neighber);
}
}
}
}
}
return n-res;
}
};
```