thảo luận Leetcode mỗi ngày

Python:
class Solution:
    def closedIsland(self, grid: List[List[int]]) -> int:
        m = len(grid)
        n = len(grid[0])

        def dfs(node):
            flag = True
            visited.add(node)

            x, y = node
            if x == 0 or x == m - 1 or y == 0 or y == n - 1:
                flag = False

            directions = [(-1, 0), (1, 0), (0, 1), (0, -1)]

            for u, v in directions:
                if 0 <= x + u < m and 0 <= y + v < n and (x + u, y + v) not in visited and grid[x + u][y + v] == 0:
                    if not dfs((x + u, y + v)):
                        flag = False

            return flag

        visited = set()
        res = 0
        
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == 0 and (i, j) not in visited:
                    if dfs((i, j)):
                        res += 1

        return res
 
Đang luyện theo LC Explore Cards nên múa thử Union Find :shame:

n is number of cells (rows * cols)
Time: O(n + n * alpha(n))
Space: O(n)

Use Union Find data structure to find the number of connected components then excluding ones on the borders.

Python:
class UnionFind:
    def __init__(self, n):
        self.roots = [node for node in range(n)]
        self.ranks = [1 for _ in range(n)]
        self.count = n
   
    def find(self, node):
        if self.roots[node] == node:
            return node
       
        self.roots[node] = self.find(self.roots[node])
       
        return self.roots[node]
   
    def union(self, node1, node2):
        root1 = self.find(node1)
        root2 = self.find(node2)
       
        if root1 != root2:
            if self.ranks[root1] > self.ranks[root2]:
                self.roots[root2] = root1
            elif self.ranks[root2] > self.ranks[root1]:
                self.roots[root1] = root2
            else:
                self.roots[root2] = root1
                self.ranks[root1] += 1
               
            self.count -= 1
   
class Solution:
    def closedIsland(self, grid: List[List[int]]) -> int:
        n = len(grid)
        m = len(grid[0])
       
        mapp = {}
        count = 0
        for row in range(n):
            for col in range(m):
                if grid[row][col] == 0:
                    mapp[(row, col)] = count
                    count += 1
                   
        uf = UnionFind(count)
       
        dirs = [(1, 0), (0, 1)]
        for row in range(n):
            for col in range(m):
                if grid[row][col] == 1:
                    continue
                   
                node = mapp[(row, col)]
                   
                for bottom, right in dirs:
                    xRow = row + bottom
                    xCol = col + right
                   
                    if xRow >= n or xCol >= m:
                        continue
                   
                    if grid[xRow][xCol] == 1:
                        continue
                   
                    neigh = mapp[(xRow, xCol)]
                   
                    uf.union(node, neigh)
     
        excluded = set()
        for row, col in mapp:
            node = mapp[(row, col)]
           
            if row == 0 or row == n - 1 or col == 0 or col == m - 1:
                excluded.add(uf.find(node))
           
        return uf.count - len(excluded)
thuong may bai dung uf code max gon :LOL: vi cai UF code da dai r, code UF xong ma phai code them doan code nua thi chac cu BFS DFS ma phang thui :mad::mad:
 
Đang luyện theo LC Explore Cards nên múa thử Union Find :shame:

n is number of cells (rows * cols)
Time: O(n + n * alpha(n))
Space: O(n)

Use Union Find data structure to find the number of connected components then excluding ones on the borders.

Python:
        excluded = set()
        for row, col in mapp:
            node = mapp[(row, col)]
           
            if row == 0 or row == n - 1 or col == 0 or col == m - 1:
                excluded.add(uf.find(node))
           
        return uf.count - len(excluded)
sao chỗ này ko có: if grid[row][col] == 1: continue vậy fen
 
Java:
class Solution {
    public int closedIsland(int[][] grid) {
        int maxRow = grid.length;
        int maxCol = grid[0].length;
        int ans = 0;
        boolean[][] visited = new boolean[maxRow][maxCol];
        for (int row = 0; row < maxRow; row++){
            for (int col = 0; col < maxCol; col++) {
                if (visited[row][col]) continue;
                if (grid[row][col] == 1) {
                    visited[row][col] = true;
                    continue;
                }
                if (check(row, col, grid, visited)) {
                    ans++;
                }
            }
        }

        return ans;
    }

    boolean check(int row, int col, int[][] grid, boolean[][] visited) {
        int maxRow = grid.length;
        int maxCol = grid[0].length;
        Queue<Integer> q = new LinkedList<>();
        q.add(row * 1000 + col);
        visited[row][col] = true;
        boolean ans = true;
        int[][] directions = new int[][]{{1, 0}, {-1, 0}, {0,1},{0,-1}};
        while(!q.isEmpty()){
            int num = q.poll();
            int curRow = num/1000;
            int curCol = num % 1000;
            if (curRow == 0 || curRow == maxRow - 1) {
                ans = false;
            }
            if (curCol == 0 || curCol == maxCol - 1) {
                ans = false;
            }
            for (int[] d : directions){
                int newRow = curRow + d[0];
                int newCol = curCol + d[1];
                if (newRow < 0 || newRow > maxRow - 1) continue;
                if (newCol < 0 || newCol > maxCol - 1) continue;
                if (visited[newRow][newCol]) continue;
                visited[newRow][newCol] = true;
                if (grid[newRow][newCol] == 0) q.add(newRow * 1000 + newCol);
            }
        }
        return ans;
    }
}
do phuc tap cua BFS là O(V+E) tai sao trong grid 2D, neu dung BFS se luon luon la m*n?
 
Vẫn thích làm BFS hơn DFS :byebye:
JavaScript:
function closedIsland(grid: number[][]): number {
    const m = grid.length, n = grid[0].length;
    const visited: boolean[][] = [];
    for (let i = 0; i < m; i++) {
        visited[i] = [];
        for (let j = 0; j < n; j++) {
            visited[i].push(false);
        }
    }
    let ans = 0;
    const bfs = (x: number, y: number): boolean => {
        const queue: number[][] = [];
        let isAdd = true;
        queue.push([x, y]);
        visited[x][y] = true;
        const dX = [0, 1, 0, -1];
        const dY = [-1, 0, 1, 0];
        while (queue.length) {
            const item = queue.shift();
            for (let i = 0; i < 4; i++) {
                const row = item[0] + dX[i];
                const col = item[1] + dY[i]
                if (row < 0 || row >= m || col < 0 || col >= n) {
                    isAdd = false;
                } else if (grid[row][col] === 0 && !visited[row][col]) {
                    queue.push([row, col])
                    visited[row][col] = true
                }
            }
        }
        return isAdd;

    }
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (grid[i][j] === 0 && !visited[i][j] && bfs(i, j)) {
                ans++
            }
        }
    }
    return ans;
};
 
tưởng là m(n-1) + n(m-1) sao lại ra 4mn nhỉ?. chỉ có các cạnh ngang dọc thui nha, ví dụ

hàng đầu có n phần tử thì sẽ có n -1 canh. nhân cac hàng lại ra m(n-1) tương tự như các cạnh dọc
Số đỉnh kề nhiều nhất của 1 đỉnh vẫn là 4 thôi, không bị ảnh hưởng bởi mấy đỉnh có số lượng kề nhỏ hơn đâu vì chạy vòng for 4 điểm mà, mình check thêm điểm ấy có tồn tại hay ko nữa:D
 
Last edited:
C++:
class Solution {
public:
    bool visited[101][101] = {0};
    int movex[4] = {-1, 1, 0, 0};
    int movey[4] = {0, 0, -1, 1};

    bool dfs(int x, int y, int m, int n, vector<vector<int>>& grid) {
        visited[x][y] = true;

        bool ans = true;
        if (x == 0 || x == m - 1 || y == 0 || y == n - 1) ans = false;

        for (int i = 0; i < 4; i++) {
            int newx = x + movex[i];
            int newy = y + movey[i];

            if (newx >= 0 && newx <= m - 1 && newy >= 0 && newy <= n - 1)
                if ((!visited[newx][newy]) && (grid[newx][newy] == 0))
                    ans &= dfs(newx, newy, m, n, grid);
        }

        return ans;
    }

    int closedIsland(vector<vector<int>>& grid) {
        int ans = 0;
        int m = grid.size();
        int n = grid[0].size();

        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                if ((!visited[i][j]) && (grid[i][j] == 0))
                    if (dfs(i, j, m, n, grid)) ans++;

        return ans;
    }
};
 
sao chỗ này ko có: if grid[row][col] == 1: continue vậy fen

Không bạn, cái mapp đó chỉ chứa những cells có giá trị 0 thôi nên ko cần lọc nữa. Code viết nhanh, nên chưa tối ưu lắm, đúng ra sau khi điền hết giá trị vào mapp thì ko cần đụng vào cái grid nữa.

thuong may bai dung uf code max gon :LOL: vi cai UF code da dai r, code UF xong ma phai code them doan code nua thi chac cu BFS DFS ma phang thui :mad::mad:

Kaka, bởi đang luyện nên phải viết nhiều cho nhớ đó bạn :)
 
Vẫn thích làm BFS hơn DFS
dfs dễ viết hơn do có sẵn cái stack

C++:
struct Solution {
    void dfs(int val, int r, int c, vector<vector<int>>& grid) {
        if (grid[r][c] != 0) return;
        grid[r][c] = val;
        if (r > 0) dfs(val, r - 1, c, grid);
        if (r < grid.size() - 1) dfs(val, r + 1, c, grid);
        if (c > 0) dfs(val, r, c - 1, grid);
        if (c < grid[0].size() - 1) dfs(val, r, c + 1, grid);
    }
    int closedIsland(vector<vector<int>>& grid) {
        for (int i = 0; i < grid.size(); ++i) dfs(-1, i, 0, grid), dfs(-1, i, grid[0].size() - 1, grid);
        for (int i = 0; i < grid[0].size(); ++i) dfs(-1, 0, i, grid), dfs(-1, grid.size() - 1, i, grid);
        int res = 0;
        for (int i = 1; i < grid.size() - 1; ++i)
            for (int j = 1; j < grid[0].size() - 1; ++j)
                if (grid[i][j] == 0) dfs(++res, i, j, grid);
        return res;
    }
};

tô màu như paint thoy
JiZo9zf.png
đầu tiên tô màu cái border có giá trị 0 trước thành màu -1, sau đó tô màu mấy ô số 0 bên trong, bao nhiêu màu thì bấy nhiêu đảo
 
Python:
class Solution:
    def closedIsland(self, grid: List[List[int]]) -> int:
        dirs = [(1,0),(0,1),(-1,0),(0,-1)]
        m, n = len(grid), len(grid[0])

        def dfs(i, j):
            nonlocal visit, res
            if (
                (i, j) in visit or
                i < 0 or i == m or
                j < 0 or j == n or
                grid[i][j] == 1
            ): return False
            visit.add((i, j))
            if i == 0 or i == m-1 or j == 0 or j == n-1:
                res = 0
            for di,dj in dirs:
                ni,nj = i+di,j+dj
                if (ni,nj) not in visit:
                    dfs(ni,nj)

        cnt = 0
        visit = set()
        res = 1
        for i in range(m):
            for j in range(n):
                if (i,j) not in visit and grid[i][j] == 0 and i != 0 and i != m-1 and j != 0 and j != n-1:
                    dfs(i,j)
                    cnt += res
                    res = 1
        return cnt
 
bài hnay gần giống bài hqua:amazed:
JavaScript:
function numEnclaves(grid: number[][]): number {
    const m = grid.length, n = grid[0].length;
    const visited: boolean[][] = [];
    for (let i = 0; i < m; i++) {
        visited[i] = [];
        for (let j = 0; j < n; j++) {
            visited[i].push(false);
        }
    }
    let ans = 0;
    const bfs = (x: number, y: number) => {
        const queue: number[][] = [];
        queue.push([x, y]);
        visited[x][y] = true;
        const dX = [0, 1, 0, -1];
        const dY = [-1, 0, 1, 0];
        while (queue.length) {
            const item = queue.shift();
            for (let i = 0; i < 4; i++) {
                const row = item[0] + dX[i];
                const col = item[1] + dY[i]
                if (row < 0 || row >= m || col < 0 || col >= n) {
                    continue
                } else if (grid[row][col] === 1 && !visited[row][col]) {
                    queue.push([row, col])
                    visited[row][col] = true
                }
            }
        }
        return;

    }
    for (let i = 0; i < m; ++i) {
        if (grid[i][0] == 1 && !visited[i][0]) {
            bfs(i, 0);
        }

        if (grid[i][n - 1] == 1 && !visited[i][n - 1]) {
            bfs(i, n - 1);
        }
    }

    for (let i = 0; i < n; ++i) {
        if (grid[0][i] == 1 && !visited[0][i]) {
            bfs(0, i);
        }
        if (grid[m - 1][i] == 1 && !visited[m - 1][i]) {
            bfs(m - 1, i);
        }
    }
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (grid[i][j] == 1 && !visited[i][j]) {
                ans++;
            }
        }
    }
    return ans;
};
 
2 bài liên tiếp gần giống nhau

JavaScript:
function numEnclaves(grid: number[][]): number {
    const [m, n] = [grid.length, grid[0].length];
    let result = 0;
    let count = 0;

    const dfs = (r: number, c: number): boolean => {
        if (
            r < 0 || c < 0
            || r === m || c === n
        ) {
            return false;
        }

        if (grid[r][c] === 0 || grid[r][c] === -1) {
            return true;
        }

        grid[r][c] = -1;
        count++;

        const dirX = [0, 1, 0, -1];
        const dirY = [-1, 0, 1, 0];
        let isClosed = true;
        for (let i = 0; i < 4; i++) {
            if (!dfs(r + dirX[i], c + dirY[i])) {
                isClosed = false;
            }
        }

        return isClosed;
    }

    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            count = 0;

            if (grid[i][j] === 1 && grid[i][j] !== -1 && dfs(i, j)) {
                result += count;
            }
        }
    }

    return result;
};
 
C++:
class Solution {
private:
    int dx[4] = {1, 0, -1, 0};
    int dy[4] = {0, 1, 0, -1};
    bool closed;
    int count, rows, cols, tmp;
    void dfs(vector<vector<int>>& grid, int i, int j){       
        for(int k = 0; k < 4; ++k){
            int ni = i + dx[k], nj = j + dy[k];
            if(ni < 0 || nj < 0 || ni >= rows || nj >= cols || !grid[ni][nj])
                continue;
            if(ni == 0 || nj == 0 || ni == rows - 1 || nj == cols - 1)
                closed = false;
            ++tmp;
            grid[ni][nj] = 0;
            dfs(grid, ni, nj);
        }
    }
public:
    int numEnclaves(vector<vector<int>>& grid) {
        count = 0, rows = grid.size(), cols = grid[0].size();
        for(int i = 0; i < rows; ++i){
            for(int j = 0; j < cols; ++j){
                if(!grid[i][j]) continue;
                grid[i][j] = 0;
                closed = true;
                tmp = 1;
                if(i == 0 || j == 0 || i == rows - 1 || j == cols - 1)
                    closed = false;
                dfs(grid, i, j);
                if(closed) count += tmp;
            }
        }
        return count;
    }
};
 
Python:
class Solution_DFS_recursive:
    def numEnclaves(self, grid: List[List[int]]) -> int:
        m = len(grid)
        n = len(grid[0])

        def dfs(node):
            flag = True
            visited.add(node)
            s.add(node)
            x, y = node
            if x == 0 or x == m - 1 or y == 0 or y == n - 1:
                flag = False

            directions = [(-1, 0), (1, 0), (0, 1), (0, -1)]

            for u, v in directions:
                if 0 <= x + u < m and 0 <= y + v < n and (x + u, y + v) not in visited and grid[x + u][y + v] == 1:
                    if not dfs((x + u, y + v)):
                        flag = False

            return flag

        res = 0
        visited = set()
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 1 and (i, j) not in visited:
                    s = set()
                    if dfs((i, j)):
                        res += len(s)         

        return res

Python:
class Solution_DFS_interative:
    def numEnclaves(self, grid: List[List[int]]) -> int:
        m = len(grid)
        n = len(grid[0])

        res = 0
        visited = set()
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 1 and (i, j) not in visited:
                    s = set()
                    stack = [(i, j)]
                    flag = True
                    while stack:
                        x, y = stack.pop()
                        s.add((x, y))
                        if x == 0 or x == m - 1 or y == 0 or y == n - 1:
                            flag = False

                        directions = [(-1, 0), (1, 0), (0, 1), (0, -1)]
                        for u, v in directions:
                            if 0 <= x + u < m and 0 <= y + v < n and (x + u, y + v) not in visited and grid[x + u][y + v] == 1:
                                visited.add((x + u, y + v))
                                stack.append((x + u, y + v))
                    if flag:
                        res += len(s)
        return res

Python:
    def numEnclaves(self, grid: List[List[int]]) -> int:
        m = len(grid)
        n = len(grid[0])
        visited = [[False]*n for i in range(m)]

        def dfs(row,col):
            if(row<0 or col<0 or row>=m or col>=n or grid[row][col]==0 or visited[row][col]==True):
                return
            visited[row][col] = True
            dfs(row,col-1)
            dfs(row+1,col)
            dfs(row,col+1)
            dfs(row-1,col)

        # first row and last row
        for j in range(n):
            if(grid[0][j]==1):
                dfs(0,j)
            if(grid[m-1][j]==1):
                dfs(m-1,j)
        for i in range(m):
            if(grid[i][0]==1):
                dfs(i,0)
            if(grid[i][n-1]==1):
                dfs(i,n-1)
        count = 0
        for i in range(m):
            for j in range(n):
                if(grid[i][j]==1 and not visited[i][j]):
                    count+=1
        return count


Tiện đây bác nào cho mình hỏi cách tính số node của một connected?
Mình code là cứ phải tạo set rỗng mỗi lần DFS trong vòng for rồi append vào.
Có cách code nào ngon hơn không để lưu vào template @@
 
Code:
/**
 * @param {number[][]} grid
 * @return {number}
 */
var numEnclaves = function(grid) {
    const m = grid.length, n = grid[0].length;
    const dirs = [[-1, 0], [1, 0], [0, 1], [0, -1]];
    let ans = 0;
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (grid[i][j] === 1) {
                let closed = true;
                let cntr = 0;
                const q = new Queue();
                q.push([i, j]);
                grid[i][j] = -1;
                while (!q.isEmpty()) {
                    const [ni, nj] = q.pop();
                    cntr++;
                    for (const [ii, jj] of dirs.map(d => [ni + d[0], nj + d[1]])) {
                        if (ii < 0 || ii >= m || jj < 0 || jj >= n) {
                            closed = false;
                        } else if (grid[ii][jj] === 1) {
                            grid[ii][jj] = -1;
                            q.push([ii, jj]);
                        }
                    }
                }
                ans += closed ? cntr : 0;
            }
        }
    }
    return ans;
};
 
Tiện đây bác nào cho mình hỏi cách tính số node của một connected?
Mình code là cứ phải tạo set rỗng mỗi lần DFS trong vòng for rồi append vào.
Có cách code nào ngon hơn không để lưu vào template @@

Một cách là cứ lấy length visited mới trừ cái cũ là ra cái số node của component gần nhất

Python:
last = len(visited)
  if dfs((i, j)):
    res += len(visited) - last
 
Back
Top