130. Surrounded Regions

這是一道Acceptance不到20%的Medium題躏吊。通常這種情況就是有需要細(xì)心考慮的邊界條件或者遞歸終止條件葫掉。
這題思路的話很容易想目尖,從外圍找O,找到了就用DFS或者BFS之類的把都是O的neighbor賦值成Y勇垛。然后掃兩遍脖母,把O變成X,Y變回O闲孤。

主要看看DFS部分吧谆级,比較典型的floodfill。注意終止條件寫法讼积。
另外網(wǎng)上有很多用用QUEUE實(shí)現(xiàn)了BFS肥照,也該寫寫的,今天太jb累了勤众,真的舆绎,在公司寫了一天膠水代碼,困的一B们颜。睡覺了吕朵。

public class Solution {

    public void solve(char[][] board) {
        if (board == null || board.length == 0) return;
        int row = board.length;
        int col = board[0].length;
        for (int i = 0; i < row; i++) {
            dfs(board, i, 0, row, col);
            if (col > 1)
                //這樣的話只有一列的情況不用單獨(dú)處理了
                dfs(board, i, col - 1, row, col);
        }
        //這里可以掐頭去尾
        for (int i = 1; i < col - 1; i++) {
            dfs(board, 0, i, row, col);
            if (row > 1)
                dfs(board, row - 1, i , row, col);
        }
        for (int i = 0; i < row; i++)
            for (int j = 0; j < col; j++) {
                if (board[i][j] == 'O') {
                    board[i][j] = 'X';
                }
            }

        for (int i = 0; i < row; i++)
            for (int j = 0; j < col; j++) {
                if (board[i][j] == 'Y') {
                    board[i][j] = 'O';
                }
            }
    }

    private void dfs(char[][] board, int i, int j, int row, int col) {
        if (board[i][j] == 'O') {
            board[i][j] = 'Y';
//        if (i < 0 || i > row - 1 || j < 0 || j > col - 1) return;
            if (i - 1 > 0) dfs(board, i - 1, j, row, col);
            if (i + 1 < row) dfs(board, i + 1, j, row, col);
            if (j - 1 > 0) dfs(board, i, j - 1, row, col);
            if (j + 1 < col) dfs(board, i, j + 1, row, col);
        }
    }
}

DFS猎醇,BFS可以多搜幾種解法看看,比如下面的ref里的幾種努溃;但是我看了很多種解法硫嘶,只有上面貼的這種在檢查下一次dfs是否滿足的寫法才勉強(qiáng)AC(估計(jì)速度也是很慢),其他的都會(huì)stackOverFlow梧税,我一開始覺得是哪里有邏輯問題沦疾,因?yàn)椴籄C的話一般是TLE啊,這題為什么是SOF呢第队。哮塞。〕馄蹋看了http://blog.csdn.net/ChilseaSai/article/details/50375111 之后明白了彻桃,就是典型的遞歸層數(shù)過深產(chǎn)生的啊。晾蜘。每一次遞歸都是一個(gè)棧,Leetcode給出了一些非常屌的testcase眠屎,長達(dá)幾KB的矩陣剔交。。我也是醉了:

HUGE MATRIX!

所以改衩,同樣是DFS岖常,在下一次運(yùn)行開始之前檢查,和利用終止條件檢查葫督,前者效率會(huì)高于后者(前者從本層就阻止了進(jìn)入下一層DFS竭鞍,后者是進(jìn)入下一層DFS再return)。另外橄镜,對(duì)于數(shù)據(jù)量大的testcase偎快,用BFS。

那如果不考慮那么大的test case洽胶,這題的dfs部分還可以這么寫:

    private void dfs(char[][] board, int x, int y, int row, int col) {
        if (x >= 0 &&  x < row && y >=0 && y <col && board[x][y] == 'O') {
            board[x][y] = 'Y';
            dfs(board, x - 1, y, row, col);
            dfs(board, x + 1, y, row, col);
            dfs(board, x, y - 1, row, col);
            dfs(board, x, y + 1, row, col);
        }
    }

或者這么寫:

    private void dfs(char[][] board, int i, int j, int row, int col) {
        if (i < 0 || i >= row || j < 0 || j >= col || board[i][j] != 'O') return;
        board[i][j] = 'Y';
        dfs(board, i - 1, j, row, col);
        dfs(board, i + 1, j, row, col);
        dfs(board, i, j - 1, row, col);
        dfs(board, i, j + 1, row, col);
    }

總之晒夹,能終止遞歸就可以了。

用BFS的話可以這么寫:

    public void solve(char[][] board) {
        if (board == null || board.length == 0) return;
        int row = board.length;
        int col = board[0].length;
        for (int i = 0; i < row; i++) {
            if (board[i][0] == 'O')
                bfs(board, i, 0, row, col);
            if (col > 1)
                if (board[i][col-1] == 'O')
                    //這樣的話只有一列的情況不用單獨(dú)處理了
                    bfs(board, i, col - 1, row, col);
        }
        //這里可以掐頭去尾
        for (int i = 1; i < col - 1; i++) {
            if (board[0][i] == 'O')
                bfs(board, 0, i, row, col);
            if (row > 1)
                if (board[row-1][i] == 'O')
                    bfs(board, row - 1, i, row, col);
        }
        for (int i = 0; i < row; i++)
            for (int j = 0; j < col; j++) {
                if (board[i][j] == 'O') {
                    board[i][j] = 'X';
                }
            }

        for (int i = 0; i < row; i++)
            for (int j = 0; j < col; j++) {
                if (board[i][j] == 'Y') {
                    board[i][j] = 'O';
                }
            }
    }

    private void bfs(char[][] board, int i, int j, int row, int col) {
        //泛型只能有一個(gè)參數(shù)姊氓,所以這里用了Pair保存坐標(biāo)(也可用余數(shù)和商來解析丐怯,可參考http://blog.csdn.net/ChilseaSai/article/details/50375111)
        LinkedList<Pair> queue = new LinkedList<>();
        Pair pair = new Pair(i, j);
        queue.add(pair);
        while (!queue.isEmpty()) {
            Pair p = queue.poll();
            int x = p.x;
            int y = p.y;
            //因?yàn)閒loodfill向四個(gè)方向擴(kuò)散,所以可能回到剛才蔓延過的地方翔横;如果不加這句读跷,提交的時(shí)候會(huì)TLE
            if (board[x][y] == 'Y') continue;
            if (board[x][y] == 'O') {
                board[x][y] = 'Y';
            }

            if (x - 1 >= 0 && board[x - 1][y] == 'O') {
                queue.add(new Pair(x - 1, y));
            }
            if (x + 1 < row && board[x + 1][y] == 'O') {
                queue.add(new Pair(x + 1, y));
            }
            if (y - 1 >= 0 && board[x][y - 1] == 'O') {
                queue.add(new Pair(x, y - 1));
            }
            if (y + 1 < col && board[x][y + 1] == 'O') {
                queue.add(new Pair(x, y + 1));
            }
        }
    }

    class Pair {
        int x;
        int y;
        Pair(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

再稍微提一下,遍歷四個(gè)邊的方法還可以這么寫:

    //對(duì)所有在邊上的O節(jié)點(diǎn)進(jìn)行BFS  
        for(int i=0;i<board.length;i++) {  
            for(int j=0;j<board[0].length;j++) {  
                if(i==0||i==(board.length-1)||j==0||j==(board[0].length-1)) {  
                    if(board[i][j]=='O') {  
                        Pair position = new Pair(i,j);  
                        queue.add(position);  
                    }  
                }  
            }  
        }  

參考的是這里禾唁,復(fù)雜度是一樣的都是O(m*n)效览。

另外些膨,本題還可以用并查集來實(shí)現(xiàn),leetcode的discussion里有钦铺。

http://blog.sina.com.cn/s/blog_b9285de20101j1dt.html
http://www.cnblogs.com/guyufei/p/3448824.html
http://blog.csdn.net/ChilseaSai/article/details/50375111

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末订雾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子矛洞,更是在濱河造成了極大的恐慌洼哎,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,080評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沼本,死亡現(xiàn)場離奇詭異噩峦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)抽兆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門识补,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辫红,你說我怎么就攤上這事凭涂。” “怎么了贴妻?”我有些...
    開封第一講書人閱讀 157,630評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵切油,是天一觀的道長。 經(jīng)常有香客問我名惩,道長澎胡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,554評(píng)論 1 284
  • 正文 為了忘掉前任娩鹉,我火速辦了婚禮攻谁,結(jié)果婚禮上贫导,老公的妹妹穿的比我還像新娘从橘。我一直安慰自己震桶,他們只是感情好怠噪,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,662評(píng)論 6 386
  • 文/花漫 我一把揭開白布掀亩。 她就那樣靜靜地躺著聂渊,像睡著了一般妒挎。 火紅的嫁衣襯著肌膚如雪腰埂。 梳的紋絲不亂的頭發(fā)上祠挫,一...
    開封第一講書人閱讀 49,856評(píng)論 1 290
  • 那天那槽,我揣著相機(jī)與錄音,去河邊找鬼等舔。 笑死骚灸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的慌植。 我是一名探鬼主播甚牲,決...
    沈念sama閱讀 39,014評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼义郑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了丈钙?” 一聲冷哼從身側(cè)響起非驮,我...
    開封第一講書人閱讀 37,752評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎雏赦,沒想到半個(gè)月后劫笙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,212評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡星岗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,541評(píng)論 2 327
  • 正文 我和宋清朗相戀三年填大,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俏橘。...
    茶點(diǎn)故事閱讀 38,687評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡允华,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出寥掐,到底是詐尸還是另有隱情靴寂,我是刑警寧澤,帶...
    沈念sama閱讀 34,347評(píng)論 4 331
  • 正文 年R本政府宣布曹仗,位于F島的核電站榨汤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏怎茫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,973評(píng)論 3 315
  • 文/蒙蒙 一妓灌、第九天 我趴在偏房一處隱蔽的房頂上張望轨蛤。 院中可真熱鬧,春花似錦虫埂、人聲如沸祥山。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缝呕。三九已至,卻和暖如春斧散,著一層夾襖步出監(jiān)牢的瞬間供常,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評(píng)論 1 266
  • 我被黑心中介騙來泰國打工鸡捐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栈暇,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,406評(píng)論 2 360
  • 正文 我出身青樓箍镜,卻偏偏與公主長得像源祈,于是被迫代替她去往敵國和親煎源。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,576評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容