九章演算法 Google面試題 島嶼的個數II

2021-10-09 08:08:00 字數 2851 閱讀 5938

給定 n, m, 分別代表乙個二維矩陣的行數和列數, 並給定乙個大小為 k 的二元陣列a. 初始二維矩陣全0. 二元陣列a內的k個元素代表k次操作, 設第i個元素為 ​(a[i].x, a[i].y)​, 表示把二維矩陣中下標為a[i].x行a[i].y列的元素由海洋變為島嶼. 問在每次操作之後, 二維矩陣中島嶼的數量. 你需要返回乙個大小為k的陣列。

樣例 1:

輸入: n = 4, m = 5, a = [[1,1],[0,1],[3,3],[3,4]]

輸出: [1,1,2,2]

解釋:

0. 00000

00000

00000

00000

1. 00000

01000

00000

00000

2. 01000

01000

00000

00000

3. 01000

01000

00000

00010

4. 01000

01000

00000

00011

樣例 2:

輸入: n = 3, m = 3, a = [[0,0],[0,1],[2,2],[2,1]]

輸出: [1,1,2,2]

並查集是指用集合裡的乙個元素來當這個集合的代表元

如果兩個元素所在集合的代表元相同,那麼我們就能知道這兩個元素在乙個集合當中。

如果我們想合併兩個集合,只需要把其中乙個集合的代表元改為第二個集合的代表元

我們只要讓i所在集合的代表元改為j所在集合的代表元就完成了合併操作。

注意:資料中有可能多次將乙個位置變成島嶼,第一次以後的操作都是無效的操作,跳過就好了

注意2:x->x1->x2->x3->x4->x5->x6->........->代表元t

我們在第一次尋找x的代表元的回溯的時候

順便把這條路徑的所有xi的父親改為了代表元t

這樣我們以後再次訪問x....x6....t這條鏈上的內容時候就可以很快的得到答案

//偽**for i 1:n

fa[i]=i //偽**,一開始讓所有的父親都是本身

//我們規定代表元的父親為本身,如果乙個節點的父親不是本身,說是它在乙個元素個數大於1的集合中,而且這個節點並不是代表元

function find(x) //尋找x所在集合的代表元

if(fa[x]==x)

return x; //x是代表元,直接返回

else

return fa[x]=find(fa[x]) //x不是代表元,尋找x的父親的代表元是誰,並且直接把代表元賦值給x的父親

function uniue(x,y)//合併兩個集合

fa[find(x)]=find(y)

時間複雜度

暴力做法

每次操作都會做一遍bfs ,做一遍bfs的時間複雜度是o(nm)

所以總時間複雜度是 o(knm),k是操作次數,nm是地圖長和寬

並查集

每次查詢代表元均攤是o(α)α代表反阿克曼函式,反阿克曼函式是漸進增長很慢很慢的,我們可以近似的認為每次查詢是o(1)的複雜度 我們一共有k次操作,每次操作最多並查集查詢4次,並查集合並4次,所以我們最終的時間複雜度是o(k)的

空間複雜度

n,m是輸入陣列 的長和寬

我們需要乙個fa陣列大小為nm,乙個vis陣列(標記該點有沒有變成島嶼),所以空間複雜度是o(nm)

public

class

solution

else

}public

intcalc

(intx,

inty

,intn,

intm

)public

list

<

integer

>

numislands2

(intn,

intm

,point

operators)}

//行走陣列,用於遍歷i島嶼的四周四個方向的島嶼下標int

zx=;int

zy=;if

(operators

==null

)for

(inti=

0;i<

operators

.length;i

++)//第i次操作的點 出現了新的島嶼

cnt++;

//遍歷這個島嶼的四周四個方向

for(

intk=0

;k<4;

k++)

//判斷四周的島嶼是不是和當前第i次操作的島嶼 已經在乙個集合了if(

find(fa

,calc(x

,y,n

,m))==

find(fa

,calc(nx

,ny,n

,m)))/*

如果不是在乙個集合裡,那麼i j所在的兩個集合就是連通的,可以合併算為乙個集合,然後讓島嶼數量-1。

我們只要讓i所在集合的代表元改為j所在集合的代表元就完成了合併操作

*/else

}//標記它是個島嶼

visited

.put

(calc(x

,y,n

,m),true

);ans

.add

(cnt);}

return

ans;

}}

更多題解參考:九章演算法

九章演算法 Google面試題 內積

描述 給定長度為n的a陣列,長度為k的b陣列 你可以從a陣列裡取k個數 規則如下 即每次可以從a陣列的最左邊或者最右邊取走乙個數,取走的數從陣列中移除 將取出的ai按取出的順序組成c陣列 求b與c的內積最大值 b與c內積為 i 0k 1bi ci 解釋1 a 1,4,3,2,5 b 1,2,3,4 ...

九章演算法 Google 面試題 解碼方法

有乙個訊息包含 a z 通過以下規則編碼 a 1 b 2 z 26 現在給你乙個加密過後的訊息,問有幾種解碼的方式 樣例 1 輸入 12 輸出 2 解釋 它可以被解碼為 ab 1 2 或 l 12 樣例 2 輸入 10 輸出 1 演算法 動態規劃 dp 演算法思路 思路 複雜度分析 n表示字串長度 ...

九章演算法 Google 面試題 奇怪的印表機

作者 陳近南 專欄 九章演算法 乙個奇怪的印表機列印時遵守以下兩個特殊的條件 每次只能列印同乙個字元組成的連續序列。每次列印可以在任何位置開始,在任何位置結束,列印的字元會將原來已有的字元覆蓋。給定乙個只包含小寫字母的字串,你的任務是計算用該印表機列印出這個字串所需的最少列印次數。字串長度不超過10...