描述

给定一个 n*m 大小的的矩阵,矩阵中由 ‘X' 和 'O' 构成,找到所有被 'X' 围绕的区域,并将其用 'X' 填充。
例如:
[['X','X','X','X'],
['X','O','O','X'],
['X','O','X','X'],
['X','X','O','X']]
中间的三个 ‘O’ 被 'X'围绕,因此将其填充为 'X' ,但第四行的 'O' 下方没有被 'X' 围绕,因此不改变,结果为
[['X','X','X','X'],
['X','X','X','X'],
['X','X','X','X'],
['X','X','O','X']]

数据范围:  ,矩阵中保证只含有 'X' 和 'O'
问题分析:首先最外围的状态不受其他位置的影响,所以我们需要做的就是检查中间部分的上,下,左,右
是否有'X'。但凡任何一个方向没有'X',这个位置就没有被包围。否则就是被围住的。
这个算法是简单粗暴的,有重复操作的过程,但也是最简单的。
时间复杂度O(n2m或nm2):最坏情况是全为O时,这样里面的元素每个都要查(n+m-2)次,
                           而需要查的元素总共有n*m-2(m+n-2)个,所以复杂度为n2m或nm2
空间复杂度O(1):只定义了几个变量
优化思路:定义一个结构体
 struct  A {
   bool up;//保存当前检查到的上面是否有X,有就为1,否就为0
   bool left;//保存当前检查到左边是否有X,有就为1,否就为0;
   int low;//下面开始出现x的位置
   int right;//右边开始出现x的位置
 * };
保存每个位置的左边是否出现x,上边是否出现x,因为整个遍历过程是从左向右,从上到下的,在定义一个vector<A> 型的数组,保存每次遍历结果,
这样当出现遍历到(i,j)位置只需要检查上一个是否为X,是x直接不用管,否则直接看上一个的up。同理检查左边,左边第一个是X,直接不用管,
否则看左边第一个的left值。而右边只需要看左边第一个的right是否大于当前j。同样的下边看上一个的low是否大于当前的i。
如果想进一步优化,还可以定义两个bool型数组,col[m]和row[n]。row[i]只要该行全为O,就为true,col[j]只要该列全为O就为true,
这样每次先判断row[i]和col[j] 是否为真,真直接为O。这样即使是最坏情况时间复杂度也只有O(n*m)。但就是空间复杂度高了点,对n和m比较大
还是可以用空间换时间的。
上面两个优化思路就不写了,这题目n和m也不是特别大。
class Solution {
public:
    vector<vector<char> > surroundedArea(vector<vector<char> >& board) {
        int n=board.size();
        if(n==1) return board;//只有一行直接返回
        int m=board[0].size();
        if(m==1) return board;//只有一列直接返回
        for(int i=1;i<n-1;++i)
            for(int j=1;j<m-1;++j) 
                if(board[i][j]=='O'){
                    //结果返回4,说明上下左右都有X,赋值为X,否则不做操作
                   if(check(board,i,j,n-1,m-1)==4)
                       board[i][j]='X';
                }
        return board;
    }
    int check(vector<vector<char> > &board,int i,int j,int n,int m) {
        int num=0;
        for(int k=i-1;k>=0;--k) //检查(i,j)上面
            if(board[k][j]=='X') {++num;break;}
        for(int k=i+1;k<=n;++k)//检查(i,j)下面
            if(board[k][j]=='X') {++num;break;}
        for(int k=j-1;k>=0;--k)//检查(i,j)左边
            if(board[i][k]=='X') {++num;break;}
        for(int k=j+1;k<=m;++k)//检查(i,j)右边
            if(board[i][k]=='X') {++num;break;}
        return num;
    }
};