542. 01 矩阵

题目描述

给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。

两个相邻元素间的距离为 1 。

示例

示例 1:
输入:mat = [[0,0,0],[0,1,0],[0,0,0]]
输出:[[0,0,0],[0,1,0],[0,0,0]]

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

实现

/* 解法1 bfs
int flag[4][2] = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};

typedef struct {
    int x;
    int y;
} Point;                // 节点结构体,包含横纵坐标

typedef struct {
     Point data[100000];
     int rear;
     int front;
} MyQueue;              // 队列

void initQueue(MyQueue *queue)
{
    queue->front = -1;
    queue->rear = -1;
    memset(queue->data, 0, sizeof(queue->data));
}

void push(MyQueue *a, Point x)      // 入队
{
    (a->rear)++;
    a->data[a->rear] = x;
}

bool isEmpty(MyQueue *a)    // 判空
{
    if(a->rear == a->front)
    {
        return true;
    }
    return false;
}

void pop(MyQueue* a)         // 出队
{
    a->front++;
}

// 找最短路径,想到bfs
int **updateMatrix(int **mat, int matSize, int *matColSize, int *returnSize, int **returnColumnSizes)
{
    *returnSize = 0;

    bool visited[matSize][matColSize[0]];    // 用于记录是否被访问过了,防止出现来回互相调用的情况
    memset(visited, false, sizeof(visited));

    int **res = (int**)malloc(sizeof(int*) * matSize);    // 包含matSize个指针,每个指针都指向一个matColSize[0]大小的数组
    memset(res, 0, sizeof(int*) * matSize);
    for (int i = 0; i < matSize; i++) {
        res[i] = (int*)malloc(sizeof(int) * matColSize[0]);
        memset(res[i], 0, sizeof(int) * matColSize[0]);
    }

    // bfs队列
    MyQueue queue;
    initQueue(&queue);

    for (int i = 0; i < matSize; i++) {
        for (int j = 0; j <matColSize[i]; j++) {
            if (mat[i][j] == 0) {
                Point tmp = {i, j};
                push(&queue, tmp);
                visited[i][j] = true;
            }
        }
    }

    while (!isEmpty(&queue)) {
        // 取队首元素,并bfs
        Point tmp = queue.data[queue.front + 1];
        pop(&queue);   // 出队

        // 对队首元素做bfs
        for (int i = 0; i < 4; i++) {
            Point cur;
            cur.x = tmp.x + flag[i][0];
            cur.y = tmp.y + flag[i][1];
            if (cur.x < 0 || cur.x >= matSize || cur.y < 0 || cur.y >= matColSize[0] || visited[cur.x][cur.y] == true) {
                continue;
            }

            // 走到这里,说明没有越界,并且没有访问过(没有访问过的肯定是1)
            res[cur.x][cur.y] = res[tmp.x][tmp.y] + 1;
            visited[cur.x][cur.y] = true;
            push(&queue, cur);
        }
    }
    *returnSize = matSize;
    *returnColumnSizes = (int*)malloc(sizeof(int) * matSize * matColSize[0]);   // 对于每个元素都要求最近的0,因此大小就是数组大小
    memset(*returnColumnSizes, 0, sizeof(int) * matSize * matColSize[0]);
    for (int i = 0; i < matSize * matColSize[0]; i++) {
        (*returnColumnSizes)[i] = matColSize[0];
    }
    return res;
}
*/

// 方法2:dp 动态规划
int **updateMatrix(int **mat, int matSize, int *matColSize, int *returnSize, int **returnColumnSizes)
{
    // 1. 建立res数组,保存结果
    int **res = (int**)malloc(sizeof(int*) * matSize);
    memset(res, 0, sizeof(int) * matSize);

    for (int i = 0; i < matSize; i++) {
        res[i] = (int*)malloc(sizeof(int) * matColSize[0]);
        for (int j = 0; j < matColSize[0]; j++) {
                res[i][j] = INT_MAX / 2;
        }
    }

    // 2. dp
    
    // 2.1 只有 水平向左移动 和 竖直向上移动
    for (int i = 0; i < matSize; i++) {
        for (int j = 0; j < matColSize[0]; j++) {
            if (mat[i][j] == 0) {
                res[i][j] = 0;
            } else {
                if (i > 0) {
                    res[i][j] = res[i][j] > res[i-1][j] + 1 ? res[i-1][j] + 1 : res[i][j];
                }
                if (j > 0) {
                    res[i][j] = res[i][j] > res[i][j-1] + 1 ? res[i][j-1] + 1 : res[i][j];
                }
            }
        }
    }

    // 2.2 只有 水平向左移动 和 竖直向下移动
    for (int i = matSize - 1; i >= 0; i--) {
        for (int j = 0; j < matColSize[0]; j++) {
            if (mat[i][j] != 0) {
                if (i < matSize - 1) {
                    res[i][j] = res[i][j] > res[i+1][j] + 1 ? res[i+1][j] + 1 : res[i][j];
                }
                if (j > 0) {
                    res[i][j] = res[i][j] > res[i][j-1] + 1 ? res[i][j-1] + 1 : res[i][j];
                }
            }
        }
    }

    // 2.3 只有 水平向右移动 和 竖直向上移动
    for (int i = 0; i < matSize; i++) {
        for (int j = matColSize[0] - 1; j >= 0; j--) {
            if (mat[i][j] != 0) {
                if (i > 0) {
                    res[i][j] = res[i][j] > res[i-1][j] + 1 ? res[i-1][j] + 1 : res[i][j];
                }
                if (j < matColSize[0] - 1) {
                    res[i][j] = res[i][j] > res[i][j+1] + 1 ? res[i][j+1] + 1 : res[i][j];
                }
            }
        }
    }

    // 2.4 只有 水平向右移动 和 竖直向下移动
    for (int i = matSize - 1; i >= 0; i--) {
        for (int j = matColSize[0] - 1; j >= 0; j--) {
            if (mat[i][j] != 0) {
                if (i < matSize - 1) {
                    res[i][j] = res[i][j] > res[i+1][j] + 1 ? res[i+1][j] + 1 : res[i][j];
                }
                if (j < matColSize[0] - 1) {
                    res[i][j] = res[i][j] > res[i][j+1] + 1 ? res[i][j+1] + 1 : res[i][j];
                }
            }
        }
    }

    /*
    // 2.1 左上到右下
    for (int i = 0; i < matSize; i++) {
        for (int j = 0; j < matColSize[0]; j++) {
            if (mat[i][j] == 0) {
                res[i][j] = 0;
            } else {
                if (j > 0) {
                    res[i][j] = res[i][j] > res[i][j-1] + 1 ? res[i][j-1] + 1 : res[i][j];
                }
                if (i > 0) {
                    res[i][j] = res[i][j] > res[i-1][j] + 1 ? res[i-1][j] + 1 : res[i][j];
                }
            }
        }
    }

    // 2.2 右下到左上
    for (int i = matSize - 1; i >= 0; i--) {
        for (int j = matColSize[0] - 1; j >= 0; j--) {
            if (mat[i][j] != 0) {
                if (j < matColSize[0] - 1) {
                    res[i][j] = res[i][j] > res[i][j+1] + 1 ? res[i][j+1] + 1 : res[i][j];
                }
                if (i < matSize - 1) {
                    res[i][j] = res[i][j] > res[i+1][j] + 1 ? res[i+1][j] + 1 : res[i][j];
                }
            }
        }
    }
    */
    *returnSize = matSize;
    *returnColumnSizes = (int*)malloc(sizeof(int) * matSize * matColSize[0]);
    for (int i = 0; i < matSize * matColSize[0]; i++) {
        (*returnColumnSizes)[i] = matColSize[0];
    }
    return res;
}

/*
int main()
{
    int **mat = (int**)malloc(sizeof(int*) * 3);    // 包含matSize个指针,每个指针都指向一个matColSize[0]大小的数组
    memset(mat, 0, sizeof(int*) * 3);

    int *matColSize = (int*)malloc(sizeof(int) * 3);
    for (int i = 0; i < 3; i++) {
        mat[i] = (int*)malloc(sizeof(int) * 3);
        memset(mat[i], 0, sizeof(int) * 3);
        matColSize[i] = 3;
    }
    mat[1][1] = 1;
    mat[2][0] = 1;
    mat[2][1] = 1;
    mat[2][2] = 1;

    int returnSize = 0;
    int **returnColumnSizes = (int**)malloc(sizeof(int*) * 3);
    int **res = updateMatrix(mat, 3, matColSize, &returnSize, returnColumnSizes);
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d\n", res[i][j]);
        }
    }
    return 0;
}
*/
复制代码
分类:
后端
标签: