GuilinDev

Lc0934

05 August 2008

934 Shortest Bridge

01二维数组中,有两个岛,现在需要连接两个岛成一个陆地,求连接的桥的最短长度

DFS + BFS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/** 
 * Use DFS + BFS to solve this WONDERFUL problem! 
 * Step 1: use DFS to mark the first island to another number
 * Step 2: start from the first island, doing BFS level order traversal to find number of bridges (levels)
 * until reach the second island
 * */
public int shortestBridge(int[][] A) {
    if (A.length == 0) {
        return 0;
    }

    int n = A.length;
    int m = A[0].length;
    Queue<int[]> queue = new LinkedList<>();
    boolean marked = false;

    // DFS to mark the all positions of first island to 2
    for (int i = 0; i < n; i++) {
        // WARNING: MUST use a boolean variable to check if we already marked the first island to 2. Otherwise,
        // we will only break from the inner loop, but will not jump out the outer loop
        if (marked) {
            break;
        }
        for (int j = 0; j < m; j++) {
            if (A[i][j] == 1) {
                // WARNING: MUST add all position of first island into queue as first level, they all can be the
                // starting points of BFS level order traversal
                dfs(A, i, j, queue);
                marked = true;
                break;
            }
        }
    }

    // BFS level order traversal: to count number of levels before finding the second island
    int bridge = 0;
    while (!queue.isEmpty()) {
        int size = queue.size();
        for (int i = 0; i < size; i++) {
            int[] curPoint = queue.poll();
            int x = curPoint[0];
            int y = curPoint[1];

            // WARNING: CANNOT use if else statement, must use all if statement to check all four directions
            if (x > 0 && A[x - 1][y] == 0) {
                queue.offer(new int[]{x - 1, y});
                A[x - 1][y] = 2;
            }
            if (x < n - 1 && A[x + 1][y] == 0) {
                queue.offer(new int[]{x + 1, y});
                A[x + 1][y] = 2;
            }
            if (y > 0 && A[x][y - 1] == 0) {
                queue.offer(new int[]{x, y - 1});
                A[x][y - 1] = 2;
            }
            if (y < m - 1 && A[x][y + 1] == 0) {
                queue.offer(new int[]{x, y + 1});
                A[x][y + 1] = 2;
            }

            // once we find the second island, return current bridge value
            if (x > 0 && A[x - 1][y] == 1 || x < n - 1 && A[x + 1][y] == 1
            || y > 0 && A[x][y - 1] == 1 || y < m - 1 && A[x][y + 1] == 1) {
                return bridge;
            }
        }
        bridge++;
    }
    return bridge;
}

public void dfs(int[][] grid, int i, int j, Queue<int[]> queue) {
    if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] != 1) {
        return;
    }

    grid[i][j] = 2;
    queue.offer(new int[]{i, j});
    dfs(grid, i - 1, j, queue);
    dfs(grid, i + 1, j, queue);
    dfs(grid, i, j - 1, queue);
    dfs(grid, i, j + 1, queue);
}