leetcode DFS/BFS

leetcode1254. 统计封闭岛屿的数量

1. 题目

有一个二维矩阵 grid,每个位置要么是陆地(记号为0 )要么是水域(记号为1 )。
我们从一块陆地出发,每次可以往上下左右4 个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」。
如果一座岛屿完全由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为 「封闭岛屿」。
请返回封闭岛屿的数目。

输入:
grid =
[[1,1,1,1,1,1,1,0],[1,0,0,0,0,1,1,0],[1,0,1,0,1,1,1,0],[1,0,0,0,0,1,0,1],[1,1,1,1,1,1,1,0]]
输出:2

2. 解答

/*
1.先处理四条边;
2.剩下的都是被包围的岛屿
*/

void dfs(int** grid, int row, int col, int x, int y)
{
    if (x < 0 || y < 0 || x >= row || y >= col || grid[x][y] == 1) {
        return;
    }
    grid[x][y] = 1;
    dfs(grid, row, col, x - 1, y);
    dfs(grid, row, col, x + 1, y);
    dfs(grid, row, col, x, y - 1);
    dfs(grid, row, col, x, y + 1);
    return;
}

int closedIsland(int** grid, int gridSize, int* gridColSize) {
    int count = 0;

    /* 先把地图边上的陆地变为海洋 */
    for (int i = 0; i < gridSize; i++) {
        dfs(grid, gridSize, *gridColSize, i, 0);
        dfs(grid, gridSize, *gridColSize, i, *gridColSize - 1);
    }

    for (int i = 0; i < *gridColSize; i++) {
        dfs(grid, gridSize, *gridColSize, 0, i);
        dfs(grid, gridSize, *gridColSize, gridSize - 1, i);
    }

    /* 剩下的都是被包围的了 */
    for (int i = 0; i < gridSize; i++) {
        for (int j = 0; j < *gridColSize; j++) {
            if (grid[i][j] == 0) {
                dfs(grid, gridSize, *gridColSize, i, j);
                count++;
            }
        }
    }

    return count;
}

leetcode79. 单词搜索

1. 题目

给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例:
board =
[
[‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]
]

给定 word = “ABCCED”, 返回 true
给定 word = “SEE”, 返回 true
给定 word = “ABCB”, 返回 false

2. 解答

bool isExist(char **board, int row, int col, char *word, int x, int y)
{
    if (*word == '\0') {
        return true;
    }

    if (x < 0 || y < 0 || x >= row || y >= col || board[x][y] != *word) {
        return false;
    }

    board[x][y] = '\0';
    int res = isExist(board, row, col, word + 1, x + 1, y) ||
        isExist(board, row, col, word + 1, x - 1, y) ||
        isExist(board, row, col, word + 1, x, y + 1) ||
        isExist(board, row, col, word + 1, x, y - 1);
    board[x][y] = *word;
    return res;
}

bool exist(char** board, int boardSize, int* boardColSize, char * word) {
    for (int i = 0; i < boardSize; i++) {
        for (int j = 0; j < *boardColSize; j++) {
            if (board[i][j] == word[0] && isExist(board, boardSize, *boardColSize, word, i, j)) {
                return true;
            }
        }
    }
    return false;
}

leetcode695. 岛屿的最大面积

1. 题目

给定一个包含了一些 0 和 1 的非空二维数组grid 。
一个岛屿是由一些相邻的1(代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设grid 的四个边缘都被 0(代表水)包围着。
找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)

示例 1:
[[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]]
对于上面这个给定矩阵应返回6。注意答案不应该是 11 ,因为岛屿只能包含水平或垂直的四个方向的 1 。

示例 2:
[[0,0,0,0,0,0,0,0]]

2. 解答

int dfs(int **grid, int row, int col, int x, int y)
{
    int res = 1;
    if (x < 0 || y < 0 || x >= row || y >= col || grid[x][y] == 0) {
        return 0;
    }
    grid[x][y] = 0;
    res += dfs(grid, row, col, x + 1, y) + dfs(grid, row, col, x - 1, y) +
        dfs(grid, row, col, x, y + 1) + dfs(grid, row, col, x, y - 1);
    return res;
}

int maxAreaOfIsland(int** grid, int gridSize, int* gridColSize)
{
    int res = 0;
    for (int i = 0; i < gridSize; i++) {
        for (int j = 0; j < *gridColSize; j++) {
            if (grid[i][j] == 1) {
                int temp = dfs(grid, gridSize, *gridColSize, i, j);
                if (temp > res) {
                    res = temp;
                }
            }
        }
    }

    return res;
}

剑指offer13. 机器人的运动范围

1. 题目

地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

示例 1:
输入:m = 2, n = 3, k = 1
输出:3

示例 2:
输入:m = 3, n = 1, k = 0
输出:1

提示:
1 <= n,m <= 100
0 <= k <= 20

2. 解答

int dfs(int i, int j, int m, int n, int k, int **isVisted)
{
    if (i <0 || i >= m || j<0 || j>=n || (i / 10 + i % 10 + j / 10 + j % 10)>k || isVisted[i][j] == 1) {
        return 0;
    }
    isVisted[i][j] = 1;
    return dfs(i + 1, j, m, n, k, isVisted) + dfs(i - 1, j, m, n, k, isVisted) + 
        dfs(i, j + 1, m, n, k, isVisted) + dfs(i, j - 1, m, n, k, isVisted) + 1;
}

int movingCount(int m, int n, int k) {
    int **isVisted = (int **)malloc(sizeof(int *) * m);
    for (int i = 0; i < m; i++) {
        isVisted[i] = (int *)malloc(sizeof(int) *n);
        memset(isVisted[i], 0, sizeof(int) *n);
    }

    return dfs(0, 0, m, n, k, isVisted);
}

leetcode934. 最短的桥

1. 题目

在给定的二维二进制数组A中,存在两座岛。(岛是由四面相连的 1 形成的一个最大组。)
现在,我们可以将0变为1,以使两座岛连接起来,变成一座岛。
返回必须翻转的0 的最小数目。(可以保证答案至少是 1。)

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

示例 2:
输入:[[0,1,0],[0,0,0],[0,0,1]]
输出:2

示例 3:
输入:[[1,1,1,1,1],[1,0,0,0,1],[1,0,1,0,1],[1,0,0,0,1],[1,1,1,1,1]]
输出:1

2. 解答

思路:
(1)先用DFS将其中一座岛置为2,和另一座区别开
(2)用BFS,将置为2的那座岛,一层层往外填海,直到第一次遇到另一座岛,就是最短的距离点

struct Point {
    int x;
    int y;
};

#define ROWSIZE 4
#define COLSIZE 2
int g_direction[ROWSIZE][COLSIZE] = {{ 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 }};

void dfs(int **A, int row, int col, int x, int y)
{
    for (int i = 0; i < ROWSIZE; i++) {
        int newX = x + g_direction[i][0];
        int newY = y + g_direction[i][1];
        if (newX >= 0 && newX < row && newY >= 0 && newY < col && A[newY][newY] == 1) {
            A[newX][newY] = 2;
            dfs(A, ASize, AColSize, newX, newY);
        }
    }
}

int shortestBridge(int** A, int ASize, int* AColSize)
{
    if (A == NULL) {
        return 0;
    }
    int result = 0;
    bool flag = false;
    /* 找出第一个岛并标记为2 */
    for (int i = 0; i < ASize; i++) {
        for (int j = 0; j < *AColSize; j++) {
            if (A[i][j] == 1) {
                flag = true;
                A[i][j] = 2;
                dfs(A, ASize, *AColSize, i, j);
                break;
            }
        }
        if (flag) {
            break;
        }
    }
    /* 将2放入到队列中 */
    struct Point *p = (struct Point *)malloc(sizeof(struct Point) * ASize * (*AColSize));
    if (p != NULL) {
        memset(p, 0, sizeof(struct Point) * ASize * (*AColSize));
    }

    int index = 0;
    for (int i = 0; i < ASize; i++) {
        for (int j = 0; j < *AColSize; j++) {
            if (A[i][j] == 2) {
                p[index].x = i;
                p[index].y = j;
                index++;
            }
        }
    }

    /* BFS找到2到1的最短距离 */
    int head = 0;
    int tail = index;
    while (head < tail) {
        int tempH = head;
        int tempT = tail;
        for (int i = tempH; i < tempT; i++) {
            struct Point tempP;
            tempP.x = p[i].x;
            tempP.y = p[i].y;
            for (int j = 0; j < ROWSIZE; j++) {
                int newX = tempP.x + g_direction[j][0];
                int newY = tempP.y + g_direction[j][1];

                if (!(newX >= 0 && newX < ASize && newY >= 0 && newY < *AColSize)) {
                    continue;
                }
                if (A[newX][newY] == 2) {
                    continue;
                }
                if (A[newX][newY] == 1) {
                    free(p);
                    return result;
                }

                // 把该点放入队列,进入下一个循环
                p[tail].x = newX;
                p[tail].y = newY;
                tail++;
                A[newX][newY] = 2;
            }
        }
        // 上一轮都遍历完了,下一轮从这个位置开始
        head = tempT;
        result++;
    }
    free(p);
    return result;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值