IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> LeetCode 0417「太平洋大西洋水流问题」 -> 正文阅读

[数据结构与算法]LeetCode 0417「太平洋大西洋水流问题」

文章目录

题目

有一个 m × n 的矩形岛屿,与太平洋大西洋相邻。“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界。

这个岛被分割成一个由若干方形单元格组成的网格。给定一个 m x n 的整数矩阵 heights, heights[r][c] 表示坐标 (r, c) 上单元格高于海平面的高度。

岛上雨水较多,如果相邻单元格的高度小于或等于当前单元格的高度,雨水可以直接向北、南、东、西流向相邻单元格。水可以从海洋附近的任何单元格流入海洋。

返回网格坐标 result 的 2D 列表 ,其中 result[i] = [ri, ci] 表示雨水从单元格 (ri, ci) 流动既可流向太平洋也可流向大西洋。

在这里插入图片描述

示例1:

  • 输入: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]]

提示:

  • m == heights.length
  • n == heights[r].length
  • 1 <= m, n <= 200
  • 0 <= heights[r][c] <= 105

题目来源:LeetCode

分析

我们知道,雨水是从高往低处流的,题目意思,对于每一个单元格,如果它旁边的单元格高度比它小,那么当前单元格的雨水可以流向高度低的单元格。按照这样的流向规则,如果从一个单元格开始,它的雨水通过高处往低处流的方向,既可以流向大西洋,也可以流向太平洋,那么这个单元格是满足条件的,即将此单元格位置添加到答案中。

按照正常思维,模拟雨水的流动,我们一般是从一个单元格开始,一直往旁边的单元格搜索,判断是否比当前单元格高度低,直到无法继续前进,或者可以流向海洋。但是这种算法会重复遍历每个单元格,时间复杂度太高。

采用逆向思维,我们从可以流向海洋的单元格,即矩阵的四个边界的单元格,开始反向搜索雨水可以流向边界的单元格。反向搜索时,每次只能移动到高度相同或更大的单元格,对于搜索过的单元格做标记,代表此单元格可以流向海洋。

搜索的算法可以采用深度优先搜索算法,或者广度优先搜索算法。

从矩阵的左边界和上边界的单元格开始反向搜索过的单元格,是可以流向太平洋的。从矩阵的右边界和下边界的单元格开始反向搜索过的单元格,是可以流向大西洋的。

最后,我们遍历每个单元格,如果它既可以从太平洋反向到达也可以从大西洋反向到达,那么将此单元格位置添加到答案中。

实现

package com.chenpi.no0417PacificAtlantic;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author 陈皮
 * @version 1.0
 * @description
 * @date 2022/4/27
 */
public class No0417PacificAtlantic {

  public static void main(String[] args) {
    No0417PacificAtlantic inst = new No0417PacificAtlantic();
    int[][] 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}};
//    int[][] heights = {{2, 1}, {1, 2}};
    System.out.println(inst.pacificAtlantic(heights));
  }

  // 代表四个方向
  int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

  public List<List<Integer>> pacificAtlantic(int[][] heights) {

    int m = heights.length;
    int n = heights[0].length;

    // true代表此位置可以流向太平洋
    boolean[][] pacific = new boolean[m][n];
    // true代表此位置可以流向大西洋
    boolean[][] atlantic = new boolean[m][n];

    // 最左边一排的每一个位置开始,深度优先搜索可以流向太平洋的位置
    for (int i = 0; i < m; i++) {
      dfs(heights, i, 0, pacific);
    }
    // 最上面一排的每一个位置开始,深度优先搜索可以流向太平洋的位置
    for (int j = 1; j < n; j++) {
      dfs(heights, 0, j, pacific);
    }

    // 最右边一排的每一个位置开始,深度优先搜索可以流向大西洋的位置
    for (int i = 0; i < m; i++) {
      dfs(heights, i, n - 1, atlantic);
    }
    // 最下面一排的每一个位置开始,深度优先搜索可以流向大西洋的位置
    for (int j = 0; j < n - 1; j++) {
      dfs(heights, m - 1, j, atlantic);
    }

    // 遍历每一个位置,如果能可以同时流向大西洋和太平洋,即满足条件
    List<List<Integer>> result = new ArrayList<>();
    for (int i = 0; i < m; i++) {
      for (int j = 0; j < n; j++) {
        if (pacific[i][j] && atlantic[i][j]) {
          result.add(Arrays.asList(i, j));
        }
      }
    }
    return result;
  }

  public void dfs(int[][] heights, int row, int col, boolean[][] ocean) {
    // 标记过,停止向前搜索
    if (ocean[row][col]) {
      return;
    }
    int m = heights.length;
    int n = heights[0].length;
    ocean[row][col] = true;
    // 向四个方向搜索
    for (int[] dir : dirs) {
      int newRow = row + dir[0], newCol = col + dir[1];
      // 下一个位置比当前位置高,则继续深度搜索
      if (newRow >= 0 && newRow < m && newCol >= 0 && newCol < n
          && heights[newRow][newCol] >= heights[row][col]) {
        dfs(heights, newRow, newCol, ocean);
      }
    }
  }
}

// 输出结果如下
[[0, 0], [0, 1], [1, 0], [1, 1]]

Leetcode 执行结果:

在这里插入图片描述


本次分享到此结束啦~~

如果觉得文章对你有帮助,点赞、收藏、关注、评论,您的支持就是我创作最大的动力!

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-29 12:21:18  更:2022-04-29 12:22:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 14:47:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码