Gidhub BE Developer

LeetCode : 934. Shortest Bridge

2022-05-29
goodGid

934. Shortest Bridge

Problem

You are given an n x n binary matrix grid where 1 represents land and 0 represents water.
An island is a 4-directionally connected group of 1's not connected to any other 1's. There are exactly two islands in grid.
You may change 0's to 1's to connect the two islands to form one island.
Return the smallest number of 0's you must flip to connect the two islands.

Example

Input: grid = [[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]]
Output: 1

[1] Code (22. 05. 29)

Need to Retry

n/a

Reference Code

Code 1

// ref : https://leetcode.com/problems/shortest-bridge/discuss/1448914/Java-oror-Easy-Approach-with-Explanation-oror-BFS-oror-DFS-oror-Preorder-oror-Graph
class Solution {
    public int shortestBridge(int[][] grid) {
        Queue<int[]> q = new LinkedList<>();
        boolean flag = false;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (grid[i][j]
                    == 1)  //  finding one island cell, to traverse the whole component and add it to the Queue
                {
                    dfs(grid, i, j, q);  //  Connected island cells
                    flag = true;
                    break;
                }
            }
            if (flag == true) {break;}
        }

        return findNearestIslandBFS(grid, q);
    }

    private void dfs(int[][] grid, int i, int j,
                     Queue<int[]> q) { // Preorder DFS is used to add the sub-land of island into the queue
        if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == -1 || grid[i][j] == 0) {
            return; // base case 1)index out of  bound 2)not visiting the visited node  3)not visiting the water cell
        }

        grid[i][j] = -1; // marking the node as visited, so that we don't traverse the node again
        q.offer(new int[] { i, j }); // adding the sub-land of the island into the Queue

         // CSS Border Order
        dfs(grid, i - 1, j, q); // Top
        dfs(grid, i, j + 1, q); // Right
        dfs(grid, i + 1, j, q); // Bottom
        dfs(grid, i, j - 1, q); // Left

        return;
    }

    private int findNearestIslandBFS(int[][] grid,
                                     Queue<int[]> q) { // BFS finds the shortest path length between the two points, so we use here to find the minimum distance between two point of island  // Top to Bottom Approach  // Multiple Variate BFS
        int[][] trav = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } }; // Traversing in 4 Direction

        int level = 0; // current level // source starting island level

        while (!q.isEmpty()) {
            int size = q.size(); // Level popping constraint
            while (size-- > 0) // Radially traversing breadth wise
            {
                int[] temp = q.poll(); // polling the current node
                for (int[] dirc : trav) {
                     // new co-ordinate
                    int i_ = temp[0] + dirc[0];
                    int j_ = temp[1] + dirc[1];
                    if (i_ >= grid.length || i_ < 0 || j_ >= grid[0].length || j_ < 0 || grid[i_][j_] == -1) {
                        continue; // base case 1)index out of bound 2)not visiting the visited node again
                    }

                    if (grid[i_][j_] == 1) // when we find a island cell, we return the current level(n-1)
                    {
                        return level; // previous level of the destination level // 0 1 2 ... (n-1) n, [1 -> n-1] swap required // returning the n-1 level  // n -> level of the destination level, 0 -> source starting island level
                    } else { // water cell case, we are adding it to the next level of the queue, to expand the search and to find the min path length between two island
                        grid[i_][j_] = -1; // marking it as visited, so that we dont traverse it again
                        q.offer(new int[] { i_, j_ }); // adding the the water cell into the Queue
                    }
                }
            }
            level += 1; // increasing the level
        }
        return -1; // base case
    }
} // Please do Upvote, it helps a lot

Review

  • 으… BFS로 1개의 섬을 찾는 아이디어까지는 떠올렸는데

    다른 섬을 찾는 아이디어를 떠올리지 못했다.

  • 정답 코드를 보니 다른 섬을 찾는 아이디어가 어렵진 않네 ㅎㅎ


[2] Code (23. 03. 11)

Need to Retry -> 시간 초과 발생 !!!

// Ref : https://leetcode.com/submissions/detail/913044029 
class Solution {
    private int ans = 1000000;
    private int size;
    private int[] dx = { -1, 1, 0, 0 }; // 상 하 좌 우
    private int[] dy = { 0, 0, -1, 1 };

    public int shortestBridge(int[][] grid) {
        size = grid.length;
        visitFirstIsland(grid); // [1]
        // pritn(grid);
        findShortestBridge(grid); // [2]

        return ans;
    }

    private void findShortestBridge(int[][] grid) {
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                int val = grid[i][j];
                if (val == 1) {
                    dfs(grid, i, j, -1);
                }
            }
        }
    }

    private void dfs(int[][] grid, int x, int y, int cnt) {
        if (grid[x][y] == 2 || ans <= cnt) {
            ans = Math.min(ans, cnt);
            return;
        }

        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];

            if (isRange(grid, nx, ny) && grid[nx][ny] != 1) {
                dfs(grid, nx, ny, cnt + 1);
            }
        }
    }

    private void visitFirstIsland(int[][] grid) {
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                int val = grid[i][j];
                if (val == 1) {
                    changeColor(grid, i, j);
                    return;
                }
            }
        }
    }

    private void changeColor(int[][] grid, int x, int y) {

        grid[x][y] = 2;

        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];

            if (isRange(grid, nx, ny) && grid[nx][ny] == 1) {
                changeColor(grid, nx, ny);
            }
        }

    }

    private boolean isRange(int[][] grid, int x, int y) {
        if (x < 0 || x >= size) {
            return false;
        }

        if (y < 0 || y >= size) {
            return false;
        }
        return true;
    }

    private void pritn(int[][] grid) {

        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                System.out.print(grid[i][j] + " ");
            }
            System.out.println("");
        }
    }
}
  • [1] : visitFirstIsland에서 첫 번째 섬을 2로 바꿔준다.

    그 이유는 두 번째 섬과의 구분을 하기 위해서이다.

  • [2] : 두 번째 섬에서 첫 번째 섬을 찾기 위한 코드

    DFS로 접근했는데 정답 코드를 보니 BFS로 접근했어야 했다. ㅠㅠ


Review

  • 아이디어 + 구현까지 30분 정도 소요

  • BFS + DFS의 조합을 요구하는 재미있는 문제였다.


Reference


Recommend

Index