LeetCode 803 打磚塊 困難

2021-10-16 09:39:27 字數 4434 閱讀 8944

題目

803. 打磚塊

有乙個 m x n 的二元網格,其中 1 表示磚塊,0 表示空白。磚塊 穩定(不會掉落)的前提是:

一塊磚直接連線到網格的頂部,或者

至少有一塊相鄰(4 個方向之一)磚塊 穩定 不會掉落時

給你乙個陣列 hits ,這是需要依次消除磚塊的位置。每當消除 hits[i] = (rowi, coli) 位置上的磚塊時,對應位置的磚塊(若存在)會消失,然後其他的磚塊可能因為這一消除操作而掉落。一旦磚塊掉落,它會立即從網格中消失(即,它不會落在其他穩定的磚塊上)。

返回乙個陣列 result ,其中 result[i] 表示第 i 次消除操作對應掉落的磚塊數目。

注意,消除可能指向是沒有磚塊的空白位置,如果發生這種情況,則沒有磚塊掉落。

示例 1:

輸入:grid =[[

1,0,

0,0]

,[1,

1,1,

0]], hits =[[

1,0]

]輸出:[2]

解釋:網格開始為:[[

1,0,

0,0],

[1,1

,1,0

]]消除 (1,

0) 處加粗的磚塊,得到網格:[[

1,0,

0,0]

[0,1

,1,0

]]兩個加粗的磚不再穩定,因為它們不再與頂部相連,也不再與另乙個穩定的磚相鄰,因此它們將掉落。得到網格:[[

1,0,

0,0]

,[0,

0,0,

0]]因此,結果為 [

2] 。

示例 2:

輸入:grid =[[

1,0,

0,0]

,[1,

1,0,

0]], hits =[[

1,1]

,[1,

0]]輸出:[0,

0]解釋:網格開始為:[[

1,0,

0,0]

,[1,

1,0,

0]]消除 (1,

1) 處加粗的磚塊,得到網格:[[

1,0,

0,0]

,[1,

0,0,

0]]剩下的磚都很穩定,所以不會掉落。網格保持不變:[[

1,0,

0,0]

,[1,

0,0,

0]]接下來消除 (1,

0) 處加粗的磚塊,得到網格:[[

1,0,

0,0]

,[0,

0,0,

0]]剩下的磚塊仍然是穩定的,所以不會有磚塊掉落。

因此,結果為 [0,

0] 。

m == grid.length

n == grid[i]

.length

1<= m, n <=

200grid[i]

[j] 為 0 或 1

1<= hits.length <=4*

104hits[i]

.length ==20

<= xi <= m -10

<= yi <= n -

1所有 (xi, yi) 互不相同

解題思路code

class

solution

:def

hitbricks

(self, grid: list[list[

int]

], hits: list[list[

int]])

-> list[

int]

:# ******************** 並查集模板 *************************

deffind

(x):

parent.setdefault(x,x)

if parent[x]

!= x:

parent[x]

= find(parent[x]

)return parent[x]

defunion

(x, y)

: rootx, rooty = find(x)

, find(y)

if rootx != rooty:

if rank[rootx]

< rank[rooty]

: parent[rootx]

= rooty

count[rooty]

+= count[rootx]

else

: parent[rooty]

= rootx

count[rootx]

+= count[rooty]

if rank[rootx]

== rank[rooty]

: rank[rootx]+=1

# *************** 第一步:將所有hits標記的磚塊打碎 ***************===

nr, nc =

len(grid)

,len

(grid[0]

)# 排列長度

original_grid = copy.deepcopy(grid)

# 複製原圖

for i, j in hits: grid[i]

[j]=

0# 打碎所有磚塊

# *************** 第二步:將磚塊與相鄰磚塊連線起來 ***************===

parent =

# 記錄各個位置的父節點(初始乙個虛擬屋頂)

rank =[0

]*(nr*nc+1)

# 記錄各個位置的rank(包含屋頂)

count =[1

]*(nr*nc)+[

0]# 記錄各個位置連線的節點的數量(包含屋頂)

for j in

range

(nc)

:if grid[0]

[j]==

1: union(j, nr*nc)

# 將最上面一排與屋頂連線

for r in

range(1

, nr)

:# 將剩餘磚塊相互連線

for c in

range

(nc)

:if grid[r]

[c]==1:

if grid[r-1]

[c]==

1: union(r*nc + c,

(r-1

)*nc + c)

if c >

0and grid[r]

[c-1]==

1: union(r*nc + c, r*nc + c -1)

# *************** 第三步:按照hits逆序往回補充磚塊 ***************===

res =

for r, c in hits[::

-1]:

# 逆序遍歷hits

if original_grid[r]

[c]==0:

# 若原grid當中這個位置本身沒有磚塊,即空白0)

# 則沒有磚塊掉落

continue

origin = count[find(nr*nc)

]# 找到原先與屋頂連線的磚塊的數量

if r ==

0: union(c, nr*nc)

# 若當前打擊位置是第一排, 則將補回的磚塊與屋頂連線

for x, y in

[(r+

1, c)

,(r-

1, c)

,(r, c+1)

,(r, c-1)

]:# 依次檢視四個方向if0

<= x < nr and

0<= y < nc and grid[x]

[y]==1:

# 若存在磚塊

union(r*nc + c, x*nc + y)

# 則將其與當前磚塊連線

current = count[find(nr*nc)

]# 連線完成之後,再找到現在與屋頂連線的磚塊數量

max(

0, current - origin -1)

)# 計算差值(注意需要減去當前這塊磚,因為不算做掉落)

grid[r]

[c]=

1# 補回磚塊

return res[::

-1]# 逆序返回結果

執行結果

每日一題 打磚塊 LeetCode803

如何計算每次擊碎磚塊而消失的磚塊數量 和頂部相連的磚塊不會掉落 擊碎乙個磚塊,可能使得其它與之連線的磚塊不再與頂部相連而消失 消失的磚塊數量 擊碎之前與頂部相連的磚塊數量 擊碎之後與頂部相連的磚塊數量 1 1就是直接被敲碎的那塊磚 並查集的按秩優化的秩即可以指當前子樹的高度rank,也可以指當前集合...

803 打磚塊 並查集,要學會建立連通關係

package com.heu.wsq.leetcode.bingchaji 803.打磚塊 author wsq date 2021 1 16 有乙個 m x n 的二元網格,其中 1 表示磚塊,0 表示空白。磚塊 穩定 不會掉落 的前提是 一塊磚直接連線到網格的頂部,或者 至少有一塊相鄰 4 個...

20190907 (leetcode習題)打家劫舍

遞迴思路 從第乙個開始偷,第n個房子處偷得的最大的總錢數要麼是第n 1個房子處偷得的總錢數,要麼是第n 2個房子處偷的總錢數 當前房子存放的錢數。class solution if result index 0 第index個房子處偷得的最大的總錢數要麼是上乙個房子處取得的最大的總錢數,要麼是上上乙...