417. 太平洋大西洋水流问题

147 阅读2分钟

题目描述

给定一个 m x n 的非负整数矩阵来表示一片大陆上各个单元格的高度。“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界。

规定水流只能按照上、下、左、右四个方向流动,且只能从高到低或者在同等高度上流动。

请找出那些水流既可以流动到“太平洋”,又能流动到“大西洋”的陆地单元的坐标。

提示:

输出坐标的顺序不重要 m 和 n 都小于150  

示例

示例:
给定下面的 5x5 矩阵:

截屏2021-09-09 下午11.21.08.png

来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/pa…

实现

// 4个方向进行遍历
void dfs(int **matrix, int x, int y, int **flow, int matrixSize, int *matrixColSize)
{
    int area[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};    // 表示坐标可以移动的方向,(i不变,j+1或j-1; j不变,i+1或i-1)
    for (int i = 0; i < 4; i++) {
        int newX = x + area[i][0];
        int newY = y + area[i][1];

        if (newX < 0 || newX >= matrixSize || newY < 0 || newY >= matrixColSize[0]) {
            continue;
        }
        if (flow[newX][newY] == 0 && matrix[newX][newY] >= matrix[x][y]) {
            flow[newX][newY] = 1;
            dfs(matrix, newX, newY, flow, matrixSize, matrixColSize);
        }
    }
}

int **pacificAtlantic(int **matrix, int matrixSize, int *matrixColSize, int *returnSize, int **returnColumnSizes)
{
    *returnSize = 0;
    if (matrix == NULL || matrixSize == 0) {
        returnColumnSizes = NULL;
        return NULL;
    }
    
    // 分配空间以及初始化
    int **pacificFlow = (int **)malloc(matrixColSize[0] * matrixSize * sizeof(int*));     // 标记是否可流到太平洋
    if (pacificFlow != NULL) {
        memset(pacificFlow, 0 , matrixColSize[0] * matrixSize * sizeof(int*));
    }

    int **atlanticFlow = (int **)malloc(matrixColSize[0] * matrixSize * sizeof(int*));    // 标记是否可流到大西洋
    if (atlanticFlow != NULL) {
        memset(atlanticFlow, 0 , matrixColSize[0] * matrixSize * sizeof(int*));
    }

    // 初始化
    for (int i = 0; i < matrixSize; i++) {
        pacificFlow[i] = (int*)malloc(matrixColSize[0] * sizeof(int));
        memset(pacificFlow[i], 0 , matrixColSize[0] * sizeof(int));

        atlanticFlow[i] = (int*)malloc(matrixColSize[0] * sizeof(int));
        memset(atlanticFlow[i], 0 , matrixColSize[0] * sizeof(int));
    }
    
    // 返回结果的指针分配空间及初始化
    *returnColumnSizes = (int*)malloc(sizeof(int) * matrixColSize[0] * matrixSize);
    int **result = (int**)malloc(sizeof(int*) * matrixColSize[0] * matrixSize);
    if (result != NULL) {
        memset(result, 0 , matrixColSize[0] * matrixSize * sizeof(int*));
    }

    // DFS 从太平洋和大西洋(4个边界)分别往中间进行搜索(下一个节点的满足条件是比该节点的值大),用2个数组分别记录每一个点是否可以流向2个大洋,
    // 最后对2个数组进行遍历,找到满足要求的点。
    for (int i = 0; i < matrixSize; i++) {
        for (int j = 0; j < matrixColSize[0]; j++) {
            if ((i == 0 || j == 0) && (pacificFlow[i][j] == 0)) {    // 从上方和左方出发
                pacificFlow[i][j] = 1;
                dfs(matrix, i, j, pacificFlow, matrixSize, matrixColSize);
            }

            if ((i == matrixSize - 1 || j == matrixColSize[0] - 1) && (atlanticFlow[i][j] == 0)) {  // 从下方和右方出发
                atlanticFlow[i][j] = 1;
                dfs(matrix, i, j, atlanticFlow, matrixSize, matrixColSize);
            }
        }
    }
    
    // 结果中atlanticFlow和pacificFlow对应位置都为1时,表明可以到达两条河
    for (int i = 0; i < matrixSize; i++) {
        for (int j = 0; j < matrixColSize[0]; j++) {
            if (pacificFlow[i][j] == 1 && atlanticFlow[i][j] == 1) {
                result[*returnSize] = (int*)malloc(sizeof(int) * 2);
                result[*returnSize][0] = i;
                result[*returnSize][1] = j;
                (*returnSize)++;
            }
        }
    }
    for (int i = 0; i < (*returnSize); i++) {
        (*returnColumnSizes)[i] = 2;
    }
    return result;
}