1.圖像渲染
733. 圖像渲染 - 力扣(LeetCode)
1.題目解析
有一幅以?
m x n
?的二維整數數組表示的圖畫?image
?,其中?image[i][j]
?表示該圖畫的像素值大小。你也被給予三個整數?sr
?,??sc
?和?color
?。你應該從像素?image[sr][sc]
?開始對圖像進行上色?填充?。為了完成?上色工作:
- 從初始像素開始,將其顏色改為?
color
。- 對初始坐標的?上下左右四個方向上?相鄰且與初始像素的原始顏色同色的像素點執行相同操作。
- 通過檢查與初始像素的原始顏色相同的相鄰像素并修改其顏色來繼續?重復?此過程。
- 當?沒有?其它原始顏色的相鄰像素時?停止?操作。
最后返回經過上色渲染?修改?后的圖像?。
2.示例
示例 1:
輸入:image = [[1,1,1],[1,1,0],[1,0,1]],sr = 1, sc = 1, color = 2
輸出:[[2,2,2],[2,2,0],[2,0,1]]
解釋:在圖像的正中間,坐標?
(sr,sc)=(1,1)
?(即紅色像素),在路徑上所有符合條件的像素點的顏色都被更改成相同的新顏色(即藍色像素)。注意,右下角的像素?沒有?更改為2,因為它不是在上下左右四個方向上與初始點相連的像素點。
3.解題思路
------本題使用的方法BFS,還有方向坐標int dx[4] = {0, 0, 1, -1}; int dy[4] = {1, -1, 0, 0};
- 參數:
-
color
:新填充顏色,用于替換與起始點顏色不同的區域。 -
sr
和sc
:起始點的行和列索引。 -
image
:輸入圖像,是一個二維整數矩陣,其中每個元素表示像素值。
-
-
檢查起始點顏色是否與新顏色相同,如果相同,直接返回原始圖像。
-
獲取圖像的行數
m
和列數n
。 -
初始化一個隊列
q
,將起始點 (sr
,sc
) 入隊。 -
當隊列不為空時,執行 BFS 遍歷:
-
彈出隊列頭部的點,獲取當前點的坐標 (
a
,b
)。 -
檢查當前點的顏色,如果已經是新顏色,跳過。
-
將新顏色賦值給當前點。
-
遍歷當前點的四個方向,如果相鄰點在圖像范圍內且顏色與起始點相同,將其加入隊列。
-
4.代碼實現
class Solution {typedef pair<int , int> PII;//定義方向變量int dx[4] = {0 , 0 , 1 , -1};int dy[4] = {1 , -1 , 0 , 0};
public:vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) {int prev = image[sr][sc];if(prev == color) return image;int m = image.size(), n = image[0].size();queue<PII> q;q.push({sr , sc});while(! q.empty()){auto [a , b] = q.front();image [a][b] = color;q.pop();for(int i = 0; i < 4; i++){int x = a + dx[i], y = b + dy[i];if(x >= 0 && x < m && y >= 0 && y < n && image[x][y] == prev )q.push({x , y});}} return image;}
};
2.島嶼數量
200. 島嶼數量 - 力扣(LeetCode)
1.題目解析
給你一個由?
'1'
(陸地)和?'0'
(水)組成的的二維網格,請你計算網格中島嶼的數量。島嶼總是被水包圍,并且每座島嶼只能由水平方向和/或豎直方向上相鄰的陸地連接形成。
此外,你可以假設該網格的四條邊均被水包圍。
2.示例
示例 1:
輸入:grid = [["1","1","1","1","0"],["1","1","0","1","0"],["1","1","0","0","0"],["0","0","0","0","0"] ] 輸出:1示例 2:
輸入:grid = [["1","1","0","0","0"],["1","1","0","0","0"],["0","0","1","0","0"],["0","0","0","1","1"] ] 輸出:3
3.解題思路
遍歷整個矩陣,每次找到「?塊陸地」的時候:
? 說明找到「?個島嶼」,記錄到最終結果 ret ??;
? 并且將這個陸地相連的所有陸地,也就是這塊「島嶼」,全部「變成海洋」。這樣的話,我們下次 遍歷到這塊島嶼的時候,它「已經是海洋」了,不會影響最終結果。
? 其中「變成海洋」的操作,可以利?「深搜」和「寬搜」解決,其實就是733.圖像渲染這道題~
-
bfs
方法:-
使用
queue
實現廣度優先搜索。 -
將起始點
(i, j)
入隊,并標記為已訪問。 -
當隊列不為空時,循環處理隊列中的點。
-
對于每個點,檢查四個方向的相鄰單元格。
-
如果相鄰單元格在網格范圍內、未訪問過、且值為 '1',則將其加入隊列,并標記為已訪問。
-
-
numIslands
方法:-
初始化島嶼數量
ret
為 0。 -
遍歷網格的每個單元格,對于值為 '1' 的單元格,如果未訪問過,則調用
bfs
方法進行搜索,并增加島嶼計數。 -
返回計算得到的島嶼數量。
-
4.代碼實現
class Solution {int m, n;int dx[4] = {0, 0, 1, -1};int dy[4] = {1, -1, 0, 0};bool visi[301][301];public:void bfs(vector<vector<char>>& grid , int i, int j){queue<pair<int , int>> q;q.push({i , j});visi[i][j] = true;while(q.size()){auto [a , b] = q.front();q.pop();for(int k = 0; k < 4; k++){int x = a + dx[k], y = b + dy[k];if(x >= 0 && x < m && y >= 0 && y < n && !visi[x][y] && grid[x][y] == '1'){q.push({x , y});visi[x][y] = true;}}}}int numIslands(vector<vector<char>>& grid) {m = grid.size(), n = grid[0].size();int ret = 0;for(int i = 0; i < m; i++)for(int j = 0; j < n; j++){if(grid[i][j] == '1' && !visi[i][j]){ret++;bfs(grid, i ,j);}}return ret;}
};
?3.島嶼的最大面積
1.題目解析
給你一個大小為?
m x n
?的二進制矩陣?grid
?。島嶼?是由一些相鄰的?
1
?(代表土地) 構成的組合,這里的「相鄰」要求兩個?1
?必須在?水平或者豎直的四個方向上?相鄰。你可以假設?grid
?的四個邊緣都被?0
(代表水)包圍著。島嶼的面積是島上值為?
1
?的單元格的數目。計算并返回?
grid
?中最大的島嶼面積。如果沒有島嶼,則返回面積為?0
?。
2.示例
示例 1:
輸入:grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]] 輸出:6 解釋:答案不應該是 11,因為島嶼只能包含水平或垂直這四個方向上的 1示例 2:
輸入:grid = [[0,0,0,0,0,0,0,0]] 輸出:0
3.解題思路
1.與第二道例題島嶼數量類似,只需定義一個計數器,來計算個數。
2.注意方向變量(dx、dy)的使用
3.還要讓visi進行賦值
4.代碼實現
class Solution {int m, n;int dx[4] = {0, 0, 1, -1};int dy[4] = {1, -1, 0, 0};bool visi[51][51];
public:int bfs(vector<vector<int>>& grid, int i, int j){queue<pair<int , int>> q;int count = 0;q.push({i , j});visi[i][j] = true;count++;while(q.size()){auto [a , b] = q.front();q.pop();for(int k = 0; k < 4; k++){int x = a + dx[k], y = b + dy[k];if(x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1 && !visi[x][y]){q.push({x , y});visi[x][y] = true;count++;}} }return count;}int maxAreaOfIsland(vector<vector<int>>& grid) {m = grid.size(), n = grid[0].size();int ret = 0;for(int i = 0; i < m; i++)for(int j = 0; j < n; j++){if(grid[i][j] == 1 && !visi[i][j]){ret = max(ret , bfs(grid , i, j));}}return ret;}
};
4.被圍繞的區域
130. 被圍繞的區域 - 力扣(LeetCode)
1.題目解析
給你一個?
m x n
?的矩陣?board
?,由若干字符?'X'
?和?'O'
?組成,捕獲?所有?被圍繞的區域:
- 連接:一個單元格與水平或垂直方向上相鄰的單元格連接。
- 區域:連接所有?
'O'
?的單元格來形成一個區域。- 圍繞:如果您可以用?
'X'
?單元格?連接這個區域,并且區域中沒有任何單元格位于?board
?邊緣,則該區域被?'X'
?單元格圍繞。通過?原地?將輸入矩陣中的所有?
'O'
?替換為?'X'
?來?捕獲被圍繞的區域。你不需要返回任何值。
2.示例
示例 1:
輸入:board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
輸出:[["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]
解釋:
在上圖中,底部的區域沒有被捕獲,因為它在 board 的邊緣并且不能被圍繞。
示例 2:
輸入:board = [["X"]]
輸出:[["X"]]
3.解題思路
正難則反。 可以先利? bfs 將與邊緣相連的 '0' 區域做上標記,然后重新遍歷矩陣,將沒有標記過的 '0' 修改成 'X' 即可。
4.代碼實現
class Solution {int dx[4] = {0, 0, 1, -1};int dy[4] = {1, -1, 0, 0};int m, n;
public:void bfs(vector<vector<char>>& board, int i, int j){queue<pair<int, int>> q;q.push({i, j});board[i][j] = '.';while(q.size()){auto [a, b] = q.front();q.pop();for(int k = 0; k < 4; k++){int x = a + dx[k], y = b + dy[k];if(x >= 0 && x < m && y >= 0 && y < n && board[x][y] == 'O'){q.push({x, y});board[x][y] = '.';}}}}void solve(vector<vector<char>>& board) {//將靠近邊上的字符'O'轉換成字符‘.’m = board.size(), n = board[0].size();for(int j = 0; j < n; j++){if(board[0][j] == 'O') bfs(board, 0, j);if(board[m - 1][j] == 'O') bfs(board, m - 1, j);}for(int i = 0; i < m; i++){if(board[i][0] == 'O') bfs(board, i, 0);if(board[i][n - 1] == 'O') bfs(board, i, n - 1);}//還原for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){if(board[i][j] == 'O') board[i][j] = 'X';else if(board[i][j] == '.') board[i][j] = 'O';}}}
};