代碼隨想錄算法訓練Day58|LeetCode417-太平洋大西洋水流問題、LeetCode827-最大人工島

太平洋大西洋水流問題

力扣417-太平洋大西洋水流問題

有一個 m × n 的矩形島嶼,與 太平洋 和 大西洋 相鄰。 “太平洋” 處于大陸的左邊界和上邊界,而 “大西洋” 處于大陸的右邊界和下邊界。

這個島被分割成一個由若干方形單元格組成的網格。給定一個 m x n 的整數矩陣 heights , heights[r] [c] 表示坐標 (r, c) 上單元格 高于海平面的高度

島上雨水較多,如果相鄰單元格的高度 小于或等于 當前單元格的高度,雨水可以直接向北、南、東、西流向相鄰單元格。水可以從海洋附近的任何單元格流入海洋。

返回網格坐標 result 的 2D 列表 ,其中 result[i] = [ri, ci] 表示雨水從單元格 (ri, ci) 流動既可流向太平洋也可流向大西洋 。

示例 1:

img

  • 輸入: heights = [[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]]
  • 輸出: [[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]

示例 2:

  • 輸入: heights = [[2,1],[1,2]]
  • 輸出: [[0,0],[0,1],[1,0],[1,1]]

解題思路

DFS 通過遞歸或棧來實現,沿著一個路徑盡可能深地搜索,直到到達最遠的節點,然后回溯并探索其他路徑。在這個問題中,從每個起始點開始,DFS 沿著四個方向探索,直到無法繼續前進或達到邊界。

class Solution {private final int[][] dir = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; // 保存四個方向// 從低向高遍歷,注意這里 visited 是引用,即可以改變傳入的 pacific 和 atlantic 的值private void dfs(int[][] heights, boolean[][] visited, int x, int y) {if (visited[x][y]) return;//如果當前坐標 (x, y) 已經被訪問過,則直接返回,不再進行后續操作。visited[x][y] = true;//只要加入,立刻標記為訪問過的節點for (int[] d : dir) { // 向四個方向遍歷 8-17int nextx = x + d[0];int nexty = y + d[1];// 超過邊界if (nextx < 0 || nextx >= heights.length || nexty < 0 || nexty >= heights[0].length) continue;// 高度不合適,注意這里是從低向高判斷if (heights[x][y] > heights[nextx][nexty]) continue;dfs(heights, visited, nextx, nexty);}}public List<List<Integer>> pacificAtlantic(int[][] heights) {List<List<Integer>> result = new ArrayList<>();int n = heights.length;int m = heights[0].length; // 這里不用擔心空指針,題目要求說了長寬都大于1// 記錄從太平洋邊出發,可以遍歷的節點boolean[][] pacific = new boolean[n][m];// 記錄從大西洋出發,可以遍歷的節點boolean[][] atlantic = new boolean[n][m];// 從最上最下行的節點出發,向高處遍歷for (int i = 0; i < n; i++) {dfs(heights, pacific, i, 0); // 遍歷最左列,接觸太平洋 dfs(heights, atlantic, i, m - 1); // 遍歷最右列,接觸大西洋 }// 從最左最右列的節點出發,向高處遍歷for (int j = 0; j < m; j++) {dfs(heights, pacific, 0, j); // 遍歷最上行,接觸太平洋dfs(heights, atlantic, n - 1, j); // 遍歷最下行,接觸大西洋}// 找到同時被太平洋和大西洋訪問的節點for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (pacific[i][j] && atlantic[i][j]) result.add(List.of(i, j));}}return result;}
}

result.add(List.of(i, j)

List.of()
List.of方法允許我們創建一個不可變的List集合,其中包含指定的元素。
List immutableList = List.of(“apple”, “banana”, “orange”);

Map.of()
Map.of方法允許我們創建一個不可變的Map集合,其中包含指定的鍵值對。
Map<String, Integer> immutableMap = Map.of(“apple”, 1, “banana”, 2, “orange”, 3);

Set.of()
Set.of方法允許我們創建一個不可變的Set集合,其中包含指定的元素。
Set immutableSet = Set.of(“apple”, “banana”, “orange”);

最大人工島

題目描述

力扣827-最大人工島

給你一個大小為 n x n 二進制矩陣 grid 。最多 只能將一格 0 變成 1 。

返回執行此操作后,grid 中最大的島嶼面積是多少?

島嶼 由一組上、下、左、右四個方向相連的 1 形成。

示例 1:

  • 輸入: grid = [[1, 0], [0, 1]]
  • 輸出: 3
  • 解釋: 將一格0變成1,最終連通兩個小島得到面積為 3 的島嶼。

示例 2:

  • 輸入: grid = [[1, 1], [1, 0]]
  • 輸出: 4
  • 解釋: 將一格0變成1,島嶼的面積擴大為 4。

示例 3:

  • 輸入: grid = [[1, 1], [1, 1]]
  • 輸出: 4
  • 解釋: 沒有0可以讓我們變成1,面積依然為 4。

解題思路

其實每次深搜遍歷計算最大島嶼面積,我們都做了很多重復的工作。

只要用一次深搜把每個島嶼的面積記錄下來就好。

第一步:一次遍歷地圖,得出各個島嶼的面積,并做編號記錄。可以使用map記錄,key為島嶼編號,value為島嶼面積 第二步:在遍歷地圖,遍歷0的方格(因為要將0變成1),并統計該1(由0變成的1)周邊島嶼面積,將其相鄰面積相加在一起,遍歷所有 0 之后,就可以得出 選一個0變成1 之后的最大面積。

拿如下地圖的島嶼情況來舉例: (1為陸地)

img

第一步,則遍歷題目,并將島嶼到編號和面積上的統計,過程如圖所示:

img

本過程代碼如下:

    private int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; // 四個方向private void dfs(int[][] grid, boolean[][] visited, int x, int y, int mark) {if (visited[x][y] || grid[x][y] == 0) return; // 終止條件:訪問過的節點 或者 遇到海水visited[x][y] = true; // 標記訪問過grid[x][y] = mark; // 給陸地標記新標簽count++;for (int i = 0; i < 4; i++) {int nextx = x + dir[i][0];int nexty = y + dir[i][1];if (nextx < 0 || nextx >= grid.length || nexty < 0 || nexty >= grid[0].length) continue;  // 越界了,直接跳過dfs(grid, visited, nextx, nexty, mark);}}public int largestIsland(int[][] grid) {int n = grid.length, m = grid[0].length;boolean[][] visited = new boolean[n][m]; // 標記訪問過的點Map<Integer, Integer> gridNum = new HashMap<>();int mark = 2; // 記錄每個島嶼的編號boolean isAllGrid = true; // 標記是否整個地圖都是陸地for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] == 0) isAllGrid = false;if (!visited[i][j] && grid[i][j] == 1) {count = 0;dfs(grid, visited, i, j, mark); // 將與其鏈接的陸地都標記上 truegridNum.put(mark, count); // 記錄每一個島嶼的面積mark++; // 記錄下一個島嶼編號}}}}

這個過程時間復雜度 n * n 。可能有錄友想:分明是兩個for循環下面套這一個dfs,時間復雜度怎么回事 n * n呢?

其實大家可以仔細看一下代碼,n * n這個方格地圖中,每個節點我們就遍歷一次,并不會重復遍歷

第二步過程如圖所示:

img

也就是遍歷每一個0的方格,并統計其相鄰島嶼面積,最后取一個最大值。

這個過程的時間復雜度也為 n * n。

所以整個解法的時間復雜度,為 n * n + n * n 也就是 n^2。

當然這里還有一個優化的點,就是 可以不用 visited數組,因為有mark來標記,所以遍歷過的grid[i] [j]是不等于1的。

不過為了讓各個變量各司其事,代碼清晰一些,完整代碼還是使用visited數組來標記。

最后,整體代碼如下:

class Solution {private int count;private int[][] dir = { { 0, 1 }, { 1, 0 }, { -1, 0 }, { 0, -1 } }; // 四個方向private void dfs(int[][] grid, boolean[][] visited, int x, int y, int mark) {if (visited[x][y] || grid[x][y] == 0)return; // 終止條件:訪問過的節點 或者 遇到海水visited[x][y] = true; // 標記訪問過grid[x][y] = mark; // 給陸地標記新標簽count++;for (int i = 0; i < 4; i++) {int nextx = x + dir[i][0];int nexty = y + dir[i][1];if (nextx < 0 || nextx >= grid.length || nexty < 0 || nexty >= grid[0].length)continue; // 越界了,直接跳過dfs(grid, visited, nextx, nexty, mark);}}public int largestIsland(int[][] grid) {int n = grid.length, m = grid[0].length;boolean[][] visited = new boolean[n][m]; // 標記訪問過的點Map<Integer, Integer> gridNum = new HashMap<>();int mark = 2; // 記錄每個島嶼的編號boolean isAllGrid = true; // 標記是否整個地圖都是陸地for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] == 0)isAllGrid = false;if (!visited[i][j] && grid[i][j] == 1) {count = 0;dfs(grid, visited, i, j, mark); // 將與其鏈接的陸地都標記上 truegridNum.put(mark, count); // 記錄每一個島嶼的面積mark++; // 記錄下一個島嶼編號}}}if (isAllGrid)return n * m; // 如果都是陸地,返回全面積// 以下邏輯是根據添加陸地的位置,計算周邊島嶼面積之和int result = 0; // 記錄最后結果Set<Integer> visitedGrid = new HashSet<>(); // 標記訪問過的島嶼for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {int currentCount = 1; // 記錄連接之后的島嶼數量visitedGrid.clear(); // 每次使用時,清空if (grid[i][j] == 0) {for (int k = 0; k < 4; k++) {int neari = i + dir[k][0]; // 計算相鄰坐標int nearj = j + dir[k][1];if (neari < 0 || neari >= grid.length || nearj < 0 || nearj >= grid[0].length)continue;if (visitedGrid.contains(grid[neari][nearj]))continue; // 添加過的島嶼不要重復添加// 把相鄰四面的島嶼數量加起來if (grid[neari][nearj] > 1) {currentCount += gridNum.get(grid[neari][nearj]);visitedGrid.add(grid[neari][nearj]); // 標記該島嶼已經添加過}}}result = Math.max(result, currentCount);}}return result;}
}

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

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

相關文章

用 Emacs 寫代碼有哪些值得推薦的插件

以下是一些用于 Emacs 寫代碼的值得推薦的插件&#xff1a; Ido-mode&#xff1a;交互式操作模式&#xff0c;它用列出當前目錄所有文件的列表來取代常規的打開文件提示符&#xff0c;能讓操作更可視化&#xff0c;快速遍歷文件。Smex&#xff1a;可替代普通的 M-x 提示符&…

【Unity】unity學習掃盲知識點

1、建議檢查下SystemInfo的引用。這個是什么 Unity的SystemInfo類提供了一種獲取關于當前硬件和操作系統的信息的方法。這包括設備類型&#xff0c;操作系統&#xff0c;處理器&#xff0c;內存&#xff0c;顯卡&#xff0c;支持的Unity特性等。使用SystemInfo類非常簡單。它的…

【python】生成完全數

定義 如果一個數恰好等于它的真因子之和&#xff0c;則稱該數為“完全數” [2]。各個小于它的約數&#xff08;真約數&#xff0c;列出某數的約數&#xff0c;去掉該數本身&#xff0c;剩下的就是它的真約數&#xff09;的和等于它本身的自然數叫做完全數&#xff08;Perfect …

Linux 查看磁盤是不是 ssd 的方法

lsblk 命令檢查 $ lsblk -d -o name,rota如果 ROTA 值為 1&#xff0c;則磁盤類型為 HDD&#xff0c;如果 ROTA 值為 0&#xff0c;則磁盤類型為 SSD。可以在上面的屏幕截圖中看到 sda 的 ROTA 值是 1&#xff0c;表示它是 HDD。 2. 檢查磁盤是否旋轉 $ cat /sys/block/sda/q…

php使用PHPExcel 導出數據表到Excel文件

直接上干貨&#xff1a;<?php$cards_list Cards::find($parameters);$objPHPExcel new \PHPExcel(); $objPHPExcel->getProperties()->setCreator("jiequan")->setLastModifiedBy("jiequan")->setTitle("card List")->setS…

Vuetify3: 根據滾動距離顯示/隱藏搜索組件

我們在使用vuetify3開發的時候&#xff0c;產品需要實現當搜索框因滾動條拉拽的時候&#xff0c;消失&#xff0c;搜索組件再次出現在頂部位置。這個我們需要獲取滾動高度&#xff0c;直接參考vuetify3 滾動指令???????&#xff0c;執行的時候發現一個問題需要設置 max-…

在什么情況下你會使用設計模式

設計模式是在軟件開發中解決常見問題的最佳實踐。它們提供了可復用的解決方案&#xff0c;使得代碼更加模塊化、易于理解和維護。以下是在什么情況下你可能會使用設計模式的一些常見情況&#xff1a; 代碼重復&#xff1a;當你發現項目中多處出現相同或相似的代碼結構時&#x…

機器學習之保存與加載

前言 模型的數據需要存儲和加載&#xff0c;這節介紹存儲和加載的方式方法。 存和加載模型權重 保存模型使用save_checkpoint接口&#xff0c;傳入網絡和指定的保存路徑&#xff0c;要加載模型權重&#xff0c;需要先創建相同模型的實例&#xff0c;然后使用load_checkpoint…

Autosar Dcm配置-0x85服務配置及使用-基于ETAS軟件

文章目錄 前言Dcm配置DcmDsdDcmDsp代碼實現總結前言 0x85服務用來控制DTC設置的開啟和關閉。某OEM3.0架構強制支持0x85服務,本文介紹ETAS工具中的配置 Dcm配置 DcmDsd 配置0x85服務 此處配置只在擴展會話下支持(具體需要根據需求決定),兩個子服務Disable為0x02,Enable…

馮諾依曼體系結構與操作系統(Linux)

文章目錄 前言馮諾依曼體系結構&#xff08;硬件&#xff09;操作系統&#xff08;軟件&#xff09;總結 前言 馮諾依曼體系結構&#xff08;硬件&#xff09; 上圖就是馮諾依曼體系結構圖&#xff0c;主要包括輸入設備&#xff0c;輸出設備&#xff0c;存儲器&#xff0c;運算…

Go高級庫存照片源碼v5.3

GoStock – 免費和付費庫存照片腳本這是一個免費和付費共享高質量庫存照片的平臺,用戶可以上傳照片與整個社區和訪客分享,并可以通過 PayPal 接收捐款。此外,用戶還可以點贊、評論、分享和收藏您最喜歡的照片。 下載 特征: 使用Laravel 10構建訂閱系統Stripe 連接漸進式網頁…

從零開始讀RocketMq源碼(一)生產者啟動

目錄 前言 獲取源碼 總概論 生產者實例 源碼 A-01:設置生產者組名稱 A-02:生產者服務啟動 B-01&#xff1a;初始化狀態 B-02&#xff1a;該方法再次對生產者組名稱進行校驗 B-03&#xff1a;判斷是否為默認生產者組名稱 B-04: 該方法是為了實例化MQClientInstance對…

白嫖A100-interLM大模型部署試用活動,親測有效-2.Git

申明 以下部分內容來源于活動教學文檔&#xff1a; Docs git 安裝 是一個開源的分布式版本控制系統&#xff0c;被廣泛用于軟件協同開發。程序員的必備基礎工具。 常用的 Git 操作 git init 初始化一個新的 Git 倉庫&#xff0c;在當前目錄創建一個 .git 隱藏文件夾來跟蹤…

Windows系統下載安裝ngnix

一 nginx下載安裝 nginx是HTTP服務器和反向代理服務器&#xff0c;功能非常豐富&#xff0c;在nginx官網首頁&#xff0c;點擊download 在download頁面下&#xff0c;可以選擇Stable version穩定版本&#xff0c;點擊下載 將下載完成的zip解壓即可&#xff0c;然乎在nginx所在…

SpringBoot新手快速入門系列教程五:基于JPA的一個Mysql簡單讀寫例子

現在我們來做一個簡單的讀寫Mysql的項目 1&#xff0c;先新建一個項目&#xff0c;我們叫它“HelloJPA”并且添加依賴 2&#xff0c;引入以下依賴&#xff1a; Spring Boot DevTools (可選&#xff0c;但推薦&#xff0c;用于開發時熱部署)Lombok&#xff08;可選&#xff0c…

三相感應電機的建模仿真(2)基于ABC相坐標系S-Fun的仿真模型

1. 概述 2. 三相感應電動機狀態方程式 3. 基于S-Function的仿真模型建立 4. 瞬態分析實例 5. 總結 6. 參考文獻 1. 概述 前面建立的三相感應電機在ABC相坐標系下的數學模型是一組周期性變系數微分方程&#xff08;其電感矩陣是轉子位置角的函數&#xff0c;轉子位置角隨時…

qt 開發筆記堆棧布局的應用

1.概要 畫面中有一處位置&#xff0c;有個按鈕點擊后&#xff0c;這片位置完全換成另一個畫面&#xff0c;這中情況特別適合用堆棧布局。 //堆棧布局的應用 #include <QStackedLayout> QStackedLayout *layout new QStackedLayout(this); layout->setCurrentIndex(…

Unity Scrollview的Scrollbar控制方法

備忘&#xff1a;碰到用scrollview自帶的scrollbar去控制滑動&#xff0c;結果發現用代碼控制scrollbar.value無效&#xff0c;搜了一下都是說用scrollRect.verticalNormalizedPosition和scrollRect.horizontalNormalizedPosition來控制的。我尋思著有關聯的scrollbar為什么用不…

【代碼隨想錄算法訓練營第六十天|并查集、卡碼網107.尋找可能存在的路徑】

文章目錄 卡碼網107.尋找可能存在的路徑 并查集基礎內容還是看代碼隨想錄 并查集 卡碼網107.尋找可能存在的路徑 純并查集的基礎應用&#xff0c;并查集只是看元素是否在同一個集合中&#xff0c;因此在加入的時候需要先查看兩個元素是否已經在一個并查集中&#xff0c;如果不…

Interview preparation--Https 工作流程

HTTP 傳輸的弊端 如上圖&#xff0c;Http進行數據傳輸的時候是明文傳輸&#xff0c;導致任何人都有可能截獲信息&#xff0c;篡改信息如果此時黑客冒充服務器&#xff0c;或者黑客竊取信息&#xff0c;則其可以返回任意信息給客戶端&#xff0c;而且不被客戶端察覺&#xff0c;…