網格圖的搜索

來自靈神網格圖題單。

1. 網格圖

1.1. LC 200 島嶼數量

這題我一開始想繁了,想維護并查集,然后看等價類個數。其實完全沒有必要。因為連通分量深搜到頭就可以直接給答案計數+1。利用vis數組維護訪問過的點,然后碰到新連通分量重新深搜即可。因為有vis數組,所以每個節點至多訪問一次,即O(nm)的復雜度。

import java.util.Arrays;class Solution {boolean[] vis;int m,n;int[][] direction = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};public int numIslands(char[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[m*n];int ans = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(grid[i][j]=='1'&&!vis[i*n+j]){dfs(grid,i,j);ans++;}}}return ans;}private void dfs(char[][] grid,int x,int y){if(vis[x*n+y]){return;}vis[x*n+y] = true;int nx,ny;for (int[] dir : direction) {nx = x+dir[0];ny = y+dir[1];if(indexValid(nx,ny)&&grid[nx][ny]=='1'){dfs(grid,nx,ny);}}}private boolean indexValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}
}

1.2. LC 695 島嶼的最大面積

這題和LC 200其實一樣的。前者統計連通分量個數,這個統計最大連通分量元素個數。還是維護vis防止走重復,遇到新連通分支就統計這個連通分支元素數量,維護最大值就行。

class Solution {boolean[] vis;int m,n;int[][] directions = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};public int maxAreaOfIsland(int[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[n*m];int max = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(!vis[i*n+j] && grid[i][j]==1){max = Math.max(max,dfs(grid,i,j));}}}return max;}private int dfs(int[][] g,int x,int y){if(vis[x*n+y]){return 0;}vis[x*n+y] = true;int nx,ny;int cnt = 0;for (int[] direction : directions) {nx = x+direction[0];ny = y+direction[1];if(indexValid(nx,ny) && g[nx][ny]==1){cnt += dfs(g,nx,ny);}}return cnt+1;}private boolean indexValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}
}

1.3. LC 面試題16.19. 水域大小

和LC695差不多。維護每個連通分量大小,排個序返回就行。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;class Solution {boolean[] vis;int m,n;int[][] dirs = new int[][]{{-1,0},{0,1},{1,0},{0,-1},{-1,-1},{-1,1},{1,-1},{1,1}};public int[] pondSizes(int[][] land) {m = land.length;n = land[0].length;vis = new boolean[m*n];List<Integer> tmp = new ArrayList<>();for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(!vis[i*n+j]&&land[i][j]==0){tmp.add(dfs(land,i,j));}}}int[] ans = new int[tmp.size()];for (int i = 0; i < tmp.size(); i++) {ans[i] = tmp.get(i);}Arrays.sort(ans);return ans;}private int dfs(int[][] l,int x,int y){if(vis[x*n+y]){return 0;}vis[x*n+y]=true;int cnt = 0;int nx,ny;for (int[] dir : dirs) {nx = x+dir[0];ny = y+dir[1];if(indexValid(nx,ny)&&l[nx][ny]==0){cnt += dfs(l,nx,ny);}}return cnt+1;}private boolean indexValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}
}

1.4. LC 463 島嶼的周長

和200/695/16.19差不多,就是查一個連通分量。記得重復邊不僅沒有增量反而-1。另外由于題目明確說了就一個連通分量,因此查到一個后可以直接結束了。

class Solution {boolean[] vis;int m,n;int[][] dirs = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};public int islandPerimeter(int[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[m*n];int ans = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(!vis[i*n+j]&&grid[i][j]==1){ans = dfs(grid,i,j);break;}}}return ans;}private int dfs(int[][] g,int x,int y){if(vis[x*n+y]){return 0;}vis[x*n+y]=true;int cnt = 4;int nx,ny;for (int[] dir : dirs) {nx = x+dir[0];ny = y+dir[1];if(indexValid(nx,ny)&&g[nx][ny]==1){cnt+=dfs(g,nx,ny)-1;}}return cnt;}private boolean indexValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}
}

1.5. LC 2658 網格圖中魚的最大數目

這題一開始讀錯題了,以為是最大化連通分量中的最大值。但實際上是最大化連通分量元素和。還是跟以前一樣套路,分開深搜維護最大值即可。

class Solution {boolean[] vis;int m,n;int[][] dirs = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};public int findMaxFish(int[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[m*n];int max = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(!vis[i*n+j]&&grid[i][j]>0){max = Math.max(max,dfs(grid,i,j));}}}return max;}private int dfs(int[][] g,int x,int y){if(vis[x*n+y]){return 0;}vis[x*n+y]=true;int nx,ny;int cnt = g[x][y];for (int[] dir : dirs) {nx = x+dir[0];ny = y+dir[1];if(indexValid(nx,ny)&&g[nx][ny]>0){cnt += dfs(g,nx,ny);}}return cnt;}private boolean indexValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}
}

1.7. LC 1020 飛地的數量

這道題雖然A了但是思路比較差。我是直接深搜,然后打一個標記位置,深搜到邊界給標記位置置true,然后深搜返回的是連通塊的大小。如果標記位為false說明連通塊沒有到邊界,這樣就可以累加。

但是更好的思路是,直接從邊界深搜,把能抵達的1全部標記出來,剩下沒標記的都是要求的。

import java.util.Arrays;class Solution {boolean[][] vis;int[][] directions = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};int m,n;boolean flag;public int numEnclaves(int[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[m][n];int sum = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(grid[i][j]==1&&!vis[i][j]){flag = false;int tmp = dfs(grid, i, j);if(!flag){sum+=tmp;}}}}return sum;}private int dfs(int[][] grid,int x,int y){if(vis[x][y]||grid[x][y]==0){return 0;}vis[x][y] = true;if(x==0||x==m-1||y==0||y==n-1){flag = true;}int nx,ny,sum;sum = 0;for (int[] direction : directions) {nx = x+direction[0];ny = y+direction[1];if(isValid(nx,ny)){sum += dfs(grid,nx,ny);}}return sum+1;}private boolean isValid(int x,int y){return x>=0 && x<m && y>=0 &&y<n;}
}

這個是我的。

class Solution {public int numEnclaves(int[][] grid) {int m = grid.length;int n = grid[0].length;for(int i = 0; i < m; i ++){if(grid[i][0] == 1) dfs(grid, i, 0, m, n);if(grid[i][n - 1] == 1) dfs(grid, i, n - 1, m , n);}for(int i = 0; i < n; i ++){if(grid[0][i] == 1) dfs(grid, 0, i, m, n);if(grid[m - 1][i] == 1) dfs(grid, m - 1, i, m ,n);}int res = 0;for(int i = 0; i < m; i ++){for(int j = 0; j < n; j ++){if(grid[i][j] == 1){res ++;}}}return res;}public void dfs(int[][] grid, int i, int j, int m, int n){if(i < 0 || j < 0 || i >= m || j >= n) return;if(grid[i][j] == 0) return;grid[i][j] = 0;dfs(grid, i + 1, j, m, n);dfs(grid, i - 1, j, m ,n);dfs(grid, i, j + 1, m, n);dfs(grid, i, j - 1, m, n);}
}

更好的思路。

1.8. LC 1254 統計封閉島嶼的數目

可以這么想,如果一個0的連通塊存在元素在邊界上,那么就不是封閉島嶼,反過來就是。這樣深搜的時候檢查是否到達過邊界。如果沒有到達過的話增1就可以了。

import java.util.Arrays;class Solution {int m,n;boolean[] vis;int[][] directions = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};public int closedIsland(int[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[m*n];Arrays.fill(vis,false);int ans = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(!vis[i*n+j]&&grid[i][j]!=1){if(!dfs(grid,i,j)){ans++;}}}}return ans;}private boolean isOnEdge(int x,int y){return x==0||y==0||x==m-1||y==n-1;}private boolean isValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}private boolean dfs(int[][] grid,int x,int y){if(grid[x][y]==1||vis[x*n+y]){return false;}vis[x*n+y] = true;int nx,ny;boolean flag = isOnEdge(x,y);for (int[] direction : directions) {nx = x+direction[0];ny = y+direction[1];if(isValid(nx,ny)){flag|=dfs(grid,nx,ny);}}return flag;}
}

1.9. LC 130 被圍繞的區域

這題別和上題一樣判斷是否連通塊有邊界元素,因為判完再染之前深搜的可能漏染了。

可以這樣,先從邊界深搜,把邊界上的O所在的連通塊全訪問掉。這樣剩下的就是內部的了(被圍繞的O),然后深搜內部染色就行。

class Solution {int m,n;boolean[][] vis;int[][] directions = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};public void solve(char[][] board) {m = board.length;n = board[0].length;vis = new boolean[m][n];for (int i = 0; i < n; i++) {if(board[0][i]=='O'&&!vis[0][i]){dfs(board,0,i,true);}}for (int i = 0; i < n; i++) {if(board[m-1][i]=='O'&&!vis[m-1][i]){dfs(board,m-1,i,true);}}for (int i = 0; i < m; i++) {if(board[i][0]=='O'&&!vis[i][0]){dfs(board,i,0,true);}}for (int i = 0; i < m; i++) {if(board[i][n-1]=='O'&&!vis[i][n-1]){dfs(board,i,n-1,true);}}for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if(board[i][j]=='O'&&!vis[i][j]){dfs(board,i,j,false);}}}}private void dfs(char[][] g,int x,int y,boolean OnEdge){if(g[x][y]=='X'||vis[x][y]){return;}vis[x][y] = true;int nx,ny;for (int[] direction : directions) {nx = x+direction[0];ny = y+direction[1];if(isValid(nx,ny)){dfs(g,nx,ny,OnEdge);}}if(!OnEdge){g[x][y] ='X';}}private boolean isValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}
}

1.10. LC 1391 檢查網格中是否存在有效路徑

這題很惡心。首先要選擇不同形狀街道的行走方向,比如第一個街道既可以從左往右,又可以從右到左;第二得保證下一個格子的街道形狀能夠對接的上這個各自的街道形狀。比如1可以拼接5但不能拼接6。這兩個條件我打表了兩個巨繁的數組。其中directions[i]是一個二維數組,表示值為i+1的單元格的行走方向,每個行走方向都是一個二維向量。accept[i]也是一個二維數組,表示值為i+1的單元格可以接受的街道形狀的對應id-1。

class Solution {int m,n;int[][][] directions = new int[][][]{{{0,-1},{0,1}},{{-1,0},{1,0}},{{0,-1},{1,0}},{{0,1},{1,0}},{{0,-1},{-1,0}},{{0,1},{-1,0}}};int[][][] accept = new int[][][]{{{0,3,5},{0,2,4}},{{1,2,3},{1,4,5}},{{0,3,5},{1,4,5}},{{0,2,4},{1,4,5}},{{0,3,5},{1,2,3}},{{0,2,4},{1,2,3}}};boolean[][] vis;public boolean hasValidPath(int[][] grid) {m = grid.length;n = grid[0].length;vis = new boolean[m][n];return dfs(grid,0,0);}private boolean dfs(int[][] grid,int x,int y){if(x==m-1 && y==n-1){return true;}vis[x][y] = true;int nx,ny;int way = grid[x][y]-1;boolean flag = false;for (int i = 0; i < directions[way].length; i++) {nx = x+directions[way][i][0];ny = y+directions[way][i][1];if(isValid(nx,ny)&&!vis[nx][ny]){if(contains(accept[way][i],grid[nx][ny]-1)){flag|=dfs(grid,nx,ny);}}}return flag;}private boolean isValid(int x,int y){return x>=0 && x<m && y>=0 && y<n;}private boolean contains(int[] arr,int target){for (int i : arr) {if(i==target){return true;}}return false;}
}

其實還好,O(mn)的。就是寫起來要有一堆規則,很惡心。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/711812.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/711812.shtml
英文地址,請注明出處:http://en.pswp.cn/news/711812.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Pinia使用

官方地址&#xff1a;Pinia | The intuitive store for Vue.js (vuejs.org)https://pinia.vuejs.org/ 1.安裝 npm install pinia npm install pinia-plugin-persistedstate Pinia是一個基于Vue 3的狀態管理庫&#xff0c;它使得管理Vue的全局狀態變得更加容易和直觀。 而…

自定義el-dialog的樣式

實現效果&#xff1a; 樣式代碼如下&#xff1a;&#xff08;可以寫在common.scss文件夾中&#xff09; .el-dialog__header {padding: 16px 20px;border-bottom: 1px solid #DCDFE6;display: flex;align-items: center;.el-dialog__title {font-size: 16px;position: relativ…

utniy urp shinyssrr插件使用

文章目錄 前言步驟1首先在URP的配置文件里添加SSR后處理2 修改RenderingPath為延遲渲染3 啟用深度紋理4 為物體添加腳本 插件下載 前言 用來實現屏幕空間反射效果 unity 版本為2021.3.8LTS&#xff0c;低版本的untiy URP的參數設置位置z可能會不同 步驟 1首先在URP的配置文件…

記錄阿里云換源失敗的慘痛教訓

聲明 首先我不是一個云服務器小白&#xff0c;但是之前一直在使用騰訊云和火山引擎的云服務器。從未見過阿里云這樣如此**的運營商。 問題 服務器到手&#xff0c;第一步在我進行sudo apt update的時候&#xff0c;也就是更新軟件包的時候&#xff0c;我發現&#xff0c;一直…

1028. 從先序遍歷還原二叉樹(三種方法:棧+遞歸+集合)

文章目錄 1028. 從先序遍歷還原二叉樹&#xff08;三種方法&#xff1a;棧遞歸集合&#xff09;一、棧 while迭代1.思路2.代碼 二、遞歸法1.思路2.代碼 三、集合存儲1.思路2.代碼 1028. 從先序遍歷還原二叉樹&#xff08;三種方法&#xff1a;棧遞歸集合&#xff09; 一、棧 wh…

hive報錯:FAILED: NullPointerException null

發現問題 起因是我虛擬機的hive不管執行什么命令都報空指針異常的錯誤 我也在網上找了很多相關問題的資料&#xff0c;發現都不是我這個問題的解決方法&#xff0c;后來在hive官網上與hive 3.1.3版本相匹配的hadoop版本是3.x的版本&#xff0c;而我的hadoop版本還是2.7.2的版本…

HTTPS的加密過程

文章目錄 前言一、為什么需要加密&#xff1f;二、只用對稱加密可以嗎&#xff1f;三、只使用非對稱加密四、雙方都使用非對稱加密五、使用非對稱加密對稱加密六、引入證書1.如何放防止數字證書被篡改&#xff1f;2.中間人有可能篡改該證書嗎&#xff1f;3.中間人有可能掉包該證…

開窗函數rank() over,dense_rank() over,row_number() over的區別

1.rank() over 查詢出指定的條件進行排名&#xff0c;條件相同排名相同的話&#xff0c;排名之間是不連續的 例如排名如 1 2 3 3 5 6 7 等&#xff0c;相同的排名會自動跳過 2.dense_rank() over 查詢出指定的條件后進行排名&#xff0c;條件相同&#xff0c;排名相同的話&…

【YOLO系列】YOLOv9論文超詳細解讀(翻譯 +學習筆記)

前言 時隔一年&#xff0c;YOLOv8還沒捂熱&#xff0c;YOLO系列最新版本——YOLOv9 終于閃亮登場&#xff01; YOLOv9的一作和v7一樣。v4也有他。 他于2017年獲得臺灣省National Central University計算機科學與信息工程博士學位&#xff0c;現在就職于該省Academia Sinica的…

【大數據】Flink SQL 語法篇(六):Temporal Join

《Flink SQL 語法篇》系列&#xff0c;共包含以下 10 篇文章&#xff1a; Flink SQL 語法篇&#xff08;一&#xff09;&#xff1a;CREATEFlink SQL 語法篇&#xff08;二&#xff09;&#xff1a;WITH、SELECT & WHERE、SELECT DISTINCTFlink SQL 語法篇&#xff08;三&…

機器視覺——硬件選型

1、相機選型 在選擇機器視覺相機時&#xff0c;通常需要考慮以下幾個方面&#xff1a; 1、分辨率&#xff1a;相機的分辨率決定了其拍攝圖像的清晰度和細節程度。根據具體的應用需求&#xff0c;可以選擇適當的分辨率范圍。 2、幀率&#xff1a;幀率表示相機每秒鐘能夠拍攝的…

2023年營養保健品線上電商市場行業分析(2024年營養保健行業未來趨勢分析)

近年來&#xff0c;受人口老齡化、養生年輕化等因素驅動&#xff0c;保健品行業增長強勁&#xff0c;加之越來越多的年輕人也加入養生大軍&#xff0c;成為保健品市場上的一股新力量&#xff0c;進一步帶動市場擴容。 鯨參謀數據顯示&#xff0c;2023年度&#xff0c;京東平臺…

[pdf]《軟件方法》2024版部分公開-共196頁

DDD領域驅動設計批評文集 做強化自測題獲得“軟件方法建模師”稱號 《軟件方法》各章合集 潘加宇《軟件方法》2024版部分公開pdf文件&#xff0c;共196頁&#xff0c;已上傳CSDN資源。 也可到以下地址下載&#xff1a; http://www.umlchina.com/url/softmeth2024.html 如果…

Ubuntu20.04 ssh終端登錄后未自動執行.bashrc

sudo vim ~/.profile輸入以下內容 if [ -n "$BASH_VERSION" ]; then if [ -f "$HOME/.bashrc" ]; then . "$HOME/.bashrc" fi fi 執行 source ~/.profile重新測試 其他答案 如果你的~/.bashrc文件在Ubuntu中沒有自動生效&#xff0c;…

3. 文檔概述(Documentation Overview)

3. 文檔概述&#xff08;Documentation Overview&#xff09; 本章節簡要介紹一下Spring Boot參考文檔。它包含本文檔其它部分的鏈接。 本文檔的最新版本可在 docs.spring.io/spring-boot/docs/current/reference/ 上獲取。 3.1 第一步&#xff08;First Steps&#xff09; …

解析電源模塊測試條件與測試步驟 快速完成測試

高溫高濕儲存測試是電源模塊環境適應性測試內容之一&#xff0c;在實際使用過程中由于應用場景不同電源所處的環境也是多樣的&#xff0c;因此需要測試電源對各種環境的適應能力&#xff0c;提高電源的性能和可靠性。 電源高溫高濕存儲測試的目的是為了測量環境對電源結構、元件…

C語言第三十三彈---動態內存管理(上)

?個人主頁&#xff1a; 熬夜學編程的小林 &#x1f497;系列專欄&#xff1a; 【C語言詳解】 【數據結構詳解】 動態內存管理 1、為什么要有動態內存分配 2、malloc和free 2.1、malloc 2.2、free 3、calloc和realloc 3.1、calloc 3.2、realloc 4、常見的動態內存的錯…

氣象數據收集

1、國家氣象科學數據中心 預報數據:需要定制,收費10萬+ 觀測數據:國家氣象信息中心-中國氣象數據網 (cma.cn)https://data.cma.cn/data/cdcdetail/dataCode/A.0012.0001.html 地面基本氣象觀測數據 滯后2天 滯后一天 路面數據同化系統,實時 國家氣象信息中心-中國氣象數…

11.以太網交換機工作原理

目錄 一、以太網協議二、以太網交換機原理三、交換機常見問題思考四、同網段數據通信全過程五、跨網段數據通信全過程六、關鍵知識七、調試命令 前言&#xff1a;在網絡中傳輸數據時需要遵循一些標準&#xff0c;以太網協議定義了數據幀在以太網上的傳輸標準&#xff0c;了解以…

android移動應用開發基礎答案,安卓工程師面試題

一線企業的app都是多線程和多進程的&#xff0c;而Android進程間通信機制就是Binder&#xff0c;原生的線程間通信則是Handler&#xff0c;Binder和Handler是了解安卓運行機制必須要掌握的一個知識點&#xff0c;更是一線企業面試必問的知識點&#xff01; 以下幾道就是大廠關于…