周围区域问题

问题描述:

    给定二维平面,格点处要么是'X',要么是'O'。求出所有由'X'围成的区域。找到这样(多个)区域后,将所有的'O'转成'X'即可。如下图所示:

X X X X

X O O X

X X O X 

X O X X

变为:

X X X X

X X X X

X X X X

X O X X

思路分析:

 可以反向思考:哪些'O'应该是保留下来的呢?从边界开始搜索,如果中间的'O'可以跟边界处连通,则应该保留下来。那些在中间的'O'则应该变成'X'。

做法:

  • 从四周的边缘处开始搜索,做广度优先遍历,对于碰到的'O',标记为其他的字符,证明已经遍历过;
  • 做完上面的广度优先搜索后,再遍历一遍整个地图,把所有的其他字符的地方恢复成"O",把仍是“O”的改成“X”即可。
import java.util.LinkedList;
import java.util.Queue;

class Node {
    int x;
    int y;
    public Node(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
class Regions {
    private int[] rowdi = {-1, 1, 0, 0};
    private int[] coldi = {0, 0, -1, 1};
    
    /**
     * BFS. 
     * Search begin from the edge to the interior. 
     * @param val
     * @return
     */
    public int[][] check(int[][] val) {
        if(val == null || val.length == 0 || val[0].length == 0)
            return val;
        Queue<Node> q = new LinkedList<Node>();
        int row = val.length;
        int col = val[0].length;
        for(int i=0; i<row; i++) {
            if(val[i][0] == 0) {
                Node n = new Node(i, 0);
                q.add(n);
                val[i][0] = 2;
            }
            if(val[i][col-1] == 0) {
                Node n = new Node(i, col-1);
                q.add(n);
                val[i][col-1] = 2;
            }
        }
        for(int j=1; j<col-1; j++) {
            if(val[0][j] == 0) {
                Node n = new Node(0, j);
                q.add(n);
                val[0][j] = 2;
            }
            if(val[row-1][j] == 0) {
                Node n = new Node(row-1, j);
                q.add(n);
                val[row-1][j] = 2;
            }
        }
        while(!q.isEmpty()) {
            Node n = q.remove();
            for(int i=0; i<rowdi.length; i++) {
                if( n.x+rowdi[i]<row && n.y+coldi[i] < col
                        && n.x+rowdi[i] >= 0 && n.y+coldi[i] >= 0) {
                    if(val[n.x+rowdi[i]][n.y+coldi[i]] == 0) {
                        Node t = new Node(n.x+rowdi[i], n.y+coldi[i]);
                        q.add(t);
                        val[n.x+rowdi[i]][n.y+coldi[i]] = 2;
                    }
                }
            }
        }
        for(int i=0; i<row; i++) {
            for(int j=0; j<col; j++) {
                if(val[i][j] == 2)
                    val[i][j] = 0;
                else if(val[i][j] == 0)
                    val[i][j] = 1;
            }
        }
        return val;
    }
}


public class SurroundedRegions {

    public static void main(String[] args) {
        int[][] val = {
                {1,1,1,1,1},
                {1,0,0,1,0},
                {1,1,1,1,0},
                {1,0,1,0,0},
                {1,1,1,1,1}};
        Regions region = new Regions();
        int[][] res = region.check(val);
        for(int i=0; i<res.length; i++) {
            for(int j=0; j<res[0].length; j++)
                System.out.print(res[i][j] + " ");
            System.out.println();
        }
    }

}

思考:前面遇到一个围棋的题目,在求某个位置的气时,也是需要求周围区域,这样连通的海洋区域就相当于气是一样的,就赋值成相同的数字。当时思路比较混乱,现在做完这个题目后可以回头完成那个题目了~ 算法就是这样,是一种思路,当具备一定的编程能力时,思路就成了最重要的东西。关键是思路!

  

原文地址:https://www.cnblogs.com/little-YTMM/p/5480942.html