`

Leetcode - Surrounded Regions

 
阅读更多
[分析]
思路1:和Number of Islands类似,但是此题用DFS会栈溢出,因此使用BFS。从四个边缘的元素开始BFS, 遇到 O 改成特殊字符M,最后没有被修改的O就是被X包围的,应当改为X, 并且把M恢复成O即可。 BFS搜索时队列中维护的是所有未展开BFS的 O,队列记录这些 O的位置。
思路2:利用union find算法,将所有边界可达的O union在一起。设置一个根节点oRoot,边界上的所有O同其union上,非边界的O同其上下左右的O进行union。扫描完board后,那些最终没有和oRoot union在一起的O是需要翻转的。实现时特别注意要将oRoot的秩设得足够大,比如设为矩阵元素个数,确保每个oRoot始终是边界可达O集合的根元素。因为在大矩阵情况下,中间可能产生比较大的秩,若oRoot秩比较小,根元素会被替换从而出错。
对比Number of Islands, 这里使用一维数组实现union find内部数据结构更简洁。

// Method 2: Union Find
public class Solution {
    public void solve(char[][] board) {
        if (board == null || board.length == 0 || board[0].length == 0)
            return;
        int rows = board.length, cols = board[0].length;
        int oRoot = rows * cols;
        initUnionFind(rows * cols);
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (board[i][j] == 'X') continue;
                int curr = i * cols + j;
                if (i == 0 || i == rows - 1 || j == 0 || j == cols - 1) {
                    union(curr, oRoot);
                } else {
                    if (j + 1 < cols && board[i][j + 1] == 'O')
                        union(curr, i * cols + j + 1);
                    if (j - 1 >= 0 && board[i][j - 1] == 'O')
                        union(curr, i * cols + j - 1);
                    if (i + 1 < rows && board[i + 1][j] == 'O')
                        union(curr, (i + 1) * cols + j);
                    if (i - 1 >= 0 && board[i - 1][j] == 'O')
                        union(curr, (i - 1) * cols + j);
                }
            }
        }
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (board[i][j] == 'O' && find(i * cols + j) != oRoot) {
                    board[i][j] = 'X';
                }
            }
        }
    }
    int[] s;
    int[] rank;
    private void initUnionFind(int n) {
        s = new int[n + 1];
        rank = new int[n + 1];
        for (int i = 0; i <= n; i++)
            s[i] = i;
        rank[n] = n + 1;
    }
    private int find(int p) {
        if (s[p] == p) return p;
        else return s[p] = find(s[p]);
    }
    private void union(int p, int q) {
        int pRoot = find(p), qRoot = find(q);
        if (pRoot == qRoot) return;
        if (rank[pRoot] < rank[qRoot]) {
            s[pRoot] = qRoot;
        } else {
            if (rank[pRoot] == rank[qRoot])
                rank[pRoot]++;
            s[qRoot] = pRoot;
        }
    }
}


// Method 1 BFS
public class Solution {
    public void solve(char[][] board) {
        if (board == null || board.length == 0 || board[0].length == 0)
            return;
        int m = board.length, n = board[0].length;
        for (int j = 0; j < n; j++) {
            if (board[0][j] == 'O') bfs(0, j, board); // row 0
            if (board[m - 1][j] == 'O') bfs(m - 1, j, board); // last row
        }
        for (int i = 0; i < m; i++) {
            if (board[i][0] == 'O') bfs(i, 0, board); // col 0
            if (board[i][n - 1] == 'O') bfs(i, n - 1, board); // last col
        }
        
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == 'O') board[i][j] = 'X';
                else if (board[i][j] == 'M') board[i][j] = 'O';
            }
        }
    }
    public void bfs(int i, int j, char[][] board) {
        LinkedList<Integer> queue = new LinkedList<Integer>();
        visit(i, j, board, queue);
        while (!queue.isEmpty()) {
            int idx = queue.poll();
            int r = idx / board[0].length;
            int c = idx % board[0].length;
            visit(r - 1, c, board, queue);
            visit(r + 1, c, board, queue);
            visit(r, c - 1, board, queue);
            visit(r, c + 1, board, queue);
        }
    }
    public void visit(int i, int j, char[][] board, LinkedList<Integer> queue) {
        if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != 'O')
            return;
        board[i][j] = 'M';
        queue.offer(i * board[0].length + j);
    }
}
分享到:
评论

相关推荐

    python-leetcode题解之130-Surrounded-Regions

    python python_leetcode题解之130_Surrounded_Regions

    leetcode1-240题中文题解,md格式,java

    7. leetcode-130-Surrounded-Regions.md:第130题,包围的区域,可能涉及二维数组处理和深度优先搜索(DFS)。 8. leetcode-29-Divide-Two-Integers.md:第29题,两数相除,涉及到整数除法和位运算。 9. leetcode-...

    Leetcode部分解答(126题)

    3. **Surrounded Regions.cpp** - 第49题,解冑处理的是矩阵中的被包围的区域。通常需要使用深度优先搜索或广度优先搜索策略,通过连通组件的概念来解决这类问题。 4. **N-Queens.cpp** - 这是经典的第51题“N皇后...

    python-leetcode面试题解之第130题被围绕的区域-题解.zip

    在本题解中,我们将深入探讨LeetCode面试中的一道经典题目——第130题“被包围的区域”(Surrounded Regions)。这是一道涉及Python编程语言的算法问题,通常在求职面试中用于测试候选人的逻辑思维和编程能力。在...

    leetcode:leetcode解题

    leetcode做过的LeetCode的题目记录一下。对一些比较经典的题型进行分类总结。数据结构 数组 字符串 队列 链表 双指针 栈 堆 树 二叉搜索... Surrounded Regions【2020-01-09】114. Flatten Binary Tree to Linked List

    javalruleetcode-WinterDash:LeetCode加强了WinterQuater

    concise](https://leetcode.com/problems/surrounded-regions/discuss/453448/java-concise-bfs) 137这种 deep copy, HashMap通吃不要太爽 Day 3 - Dec 17 12:28 199 Finished. 佛了 做完第一题就不想做了 12:54...

    leetcode添加元素使和等于-leetcode:leetcode

    Surrounded_Regions 由四周‘O’开始向内检索,利用第三个字符对可以变换的‘O’进行暂存 Word_Lader BFS,避免DFS记录以遍历的节点错误,且保证优先找到最短的路径, 按照图的方法判断任意两个节点是否差一个字母,...

Global site tag (gtag.js) - Google Analytics