(LeetCode 130)Surrounded Regions(并查集)

25 篇文章 0 订阅
23 篇文章 0 订阅

Q:
Given a 2D board containing ‘X’ and ‘O’, capture all regions surrounded by ‘X’.

A region is captured by flipping all ‘O’s into ‘X’s in that surrounded region.

For example,
X X X X
X O O X
X X O X
X O X X
After running your function, the board should be:

X X X X
X X X X
X X X X
X O X X

题意就是给你一个二维矩阵,里面包含’O’,’X’,然后把所有被’X’包围的’O’变为’X’。

solution:
这道题解法很多,BFS,DFS算法都可以使用。
这里有这道题BFS算法解法说明:
(LeetCode 130) Surrounded Regions(BFS)

本篇博客采用Union Find算法,即并查集。
并查集常用来解决连通性的问题,即将一个图中连通的部分划分出来。当我们判断图中两个点之间是否存在路径时,就可以根据判断他们是否在一个连通区域。
当数据较多时,并查集比BFS和DFS算法适用。
但是,并查集的缺陷就是不能够求出连通的两个点之间的路径,但是DFS算法或者BFS算法适用。
并查集的思想就是,同一个连通区域内的所有点的根节点是同一个。将每个点映射成一个数字。先假设每个点的根节点就是他们自己,然后我们以此输入连通的点对,然后将其中一个点的根节点赋成另一个节点的根节点,这样这两个点所在连通区域又相互连通了。
并查集的主要操作有:

  • find(int m):这是并查集的基本操作,查找m的根节点。
  • checkConnection(int m,int n):判断m,n两个点是否在一个连通区域。
  • Union(int m,int n):合并m,n两个点所在的连通区域。

当然,并查集还有较多优化,比如怎么避免并查集的树退化成一条链。合并的时候,应该尽量让小树根节点连在大树根节点上,尽量使得整个树扁平。
具体并查集的详解可以参考这篇博客:
并查集(Union-Find)算法介绍

下面贴上这道题的代码:

class Solution {
public:
    vector<int> unionset;
    vector<bool> isedge;
    void solve(vector<vector<char>>& board) {
        if(board.size()==0||board[0].size()==0)return;
        int width =board[0].size();
        int length = board.size()*board[0].size();
        unionset = vector<int>(length,0);
        isedge = vector<bool>(length,false);

        for(int i=0;i<length;i++){
            unionset[i]=i;
            int x=i/width , y=i%width;
            if((board[x][y]=='O')&&((x==0)||(x==board.size()-1)||(y==0)||(y==board[0].size()-1)))
                    isedge[i]=true;
        }

        for(int j=0;j<length;j++){
            int x=j/width, y=j%width;
            int down = x+1, right = y+1;
            if(down<board.size()&&board[x][y]==board[down][y])
             unionS(j,j+width);
            if(right<board[0].size()&&board[x][y]==board[x][right])
             unionS(j,j+1); 
        }
        for(int m=0;m<length;m++){
            int x=m/width,y=m%width;
            if(board[x][y]=='O'&&!isedge[find(m)])
            board[x][y]='X';
        }

    };
    void unionS(int m,int n){
            int rootM=find(m);
            int rootN=find(n);
            if(rootM==rootN)return;
            unionset[rootN] = rootM;
            if(isedge[rootN])isedge[rootM]=true;
    };

    int find(int p){
        while(p!=unionset[p]){
            unionset[p]=unionset[unionset[p]];
            p=unionset[p];
        }
        return p;
    };
};

但是时间消耗还是比BFS算法多,囧

Reference Link:
http://blog.csdn.net/dm_vincent/article/details/7655764
http://blog.csdn.net/gldemo/article/details/47854589

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值