Leetcode 947:移除最多的同行或同列石頭(超詳細的解法!!!)
阿新 • • 發佈:2018-12-15
在二維平面上,我們將石頭放置在一些整數座標點上。每個座標點上最多隻能有一塊石頭。
現在,move 操作將會移除與網格上的某一塊石頭共享一列或一行的一塊石頭。
我們最多能執行多少次 move 操作?
示例 1:
輸入:stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]]
輸出:5
示例 2:
輸入:stones = [[0,0],[0,2],[1,1],[2,0],[2,2]]
輸出:3
示例 3:
輸入:stones = [[0,0]]
輸出:0
提示:
1 <= stones.length <= 1000
0 <= stones[i][j] < 10000
解題思路
這個問題我拿到手首先想到的處理思路就是並查集。我們可以通過並查集很快的確定哪些元素是橫座標或者縱座標聯通(也就是確定一個集合)。我們最後的結果就是每個集合中只存放一個元素,取出其餘元素。
class Solution:
def removeStones(self, stones):
"""
:type stones: List[List[int]]
:rtype: int
"""
stones = list(map(tuple, stones))
stones_len = len(stones)
uf = collections.defaultdict()
count = stones_len
for c in stones:
uf[c] = c
def find(coor):
if coor != uf[coor]:
uf[coor] = find(uf[coor])
return uf[coor]
def union(c1, c2) :
nonlocal count
p1, p2 = find(c1), find(c2)
if p1 == p2:
return
uf[p1] = c2
count -= 1
for c1, c2 in itertools.combinations(stones, 2):
if c1[0] == c2[0] or c1[1] == c2[1]:
union(c1, c2)
return stones_len - count
實際上我們這個程式碼實現的非常不好。我們使用combinations
這個函式,這樣我們的遍歷次數增加了許多。我們能不能只遍歷一遍就知道結果呢?我們實際上可以不通過合併點,而是通過合併x
和y
座標實現,但是x
和y
座標有很多相同的元素要怎麼辦呢?我們要知道我們通過歸併點的本質其實是想要區分x
和y
座標,所以我們在歸併x
和y
座標的時候也要將其區分,一個簡單的思路就是對y
取逆。
class Solution:
def removeStones(self, stones):
"""
:type stones: List[List[int]]
:rtype: int
"""
UF = {}
def find(x):
if x != UF[x]:
UF[x] = find(UF[x])
return UF[x]
def union(x, y):
UF.setdefault(x, x)
UF.setdefault(y, y)
UF[find(x)] = find(y)
for i, j in stones:
union(i, ~j)
return len(stones) - len({find(x) for x in UF})
有了前面的思路我們不難想到這其實就是一個尋找島嶼數量的問題,通過深度優先遍歷找到島嶼的個數。
from collections import defaultdict
class Solution:
def removeStones(self, stones):
"""
:type stones: List[List[int]]
:rtype: int
"""
def dfs(i, j):
visited.add((i, j))
for y in rows[i]:
if (i, y) not in visited:
dfs(i, y)
for x in cols[j]:
if (x, j) not in visited:
dfs(x, j)
visited, island, rows, cols = set(), 0, defaultdict(list), defaultdict(list)
for i, j in stones:
rows[i].append(j)
cols[j].append(i)
for i, j in stones:
if (i, j) not in visited:
dfs(i, j)
island += 1
return len(stones) - island
最後的結果就是stones
的數量減去島嶼的數量。
reference:
我將該問題的其他語言版本新增到了我的GitHub Leetcode
如有問題,希望大家指出!!!