<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    小明思考

    Just a software engineer
    posts - 124, comments - 36, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    包圍的區域

    Posted on 2013-04-15 18:17 小明 閱讀(1561) 評論(2)  編輯  收藏 所屬分類: 數據結構和算法
    問題給定一個2D的棋盤,含有‘X'和’O',找到所有被‘X'包圍的’O',然后把該區域的‘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

    public void solve(char[][] board) {
    }

    分析:
    為了提高效率,我使用了一個mark數組來記錄所有訪問過的‘O'點,避免重復檢查,同時要避免死循環。
    每個點有四種狀態,未檢測(0),正在檢測(-1),包圍的點(1),沒有被包圍的點(2)。
    另外,為了對付很大的棋盤,避免使用遞歸而造成堆棧溢出,使用了一個檢測隊列。

    代碼如下:

    public class SurroundedRegions {
        
        private char[][] board;
        private int[][] mark;
        private int h;
        private int w;
        
        private final int S = 1; //surrounded point
        private final int NS = 2; //Not surrounded point
        private final int T = -1; //testing point, undetermined point
        
        private static class Point{
            int x,y;
            
            Point(int x,int y){
                this.x =x;
                this.y = y;
            }
        }
        
        private int test(int i,int j, List<Point> lp){
            int result = S;
            mark[i][j] = T; 
            if(i==0 || i==h-1 || j==0 || j==w-1){ //border point
                result = NS;
            }
            else{
                int[] nx={i-1,i,i,i+1};
                int[] ny={j,j-1,j+1,j};
                for(int k=0;k<4;++k){ //check the four directions
                    int x = nx[k];
                    int y = ny[k];
                    if(board[x][y]=='O'){
                        int m = mark[x][y];
                        if(m==0){
                            mark[x][y] = T; //mark as testing point to avoid duplicated visit
                            lp.add(new Point(x,y));
                        }
                        else if(m>0){
                            result =  m;
                        }
                    }
                    if(result==NS){
                        break;
                    }
                }
            }
            mark[i][j]= result;
            return result;
        }
        
        public void solve(char[][] board) {
            this.h = board.length;
            if(h<1){
                return;
            }
            this.w = board[0].length;
            
            this.board = board;
            this.mark = new int[h][w];
            
            for(int i=0;i<h;++i){
                char[] row = board[i];
                int[] mrow = mark[i];
                for(int j=0;j<w;++j){
                    char c = row[j];
                    if(c=='O' && mrow[j]==0){ //not marked point
                        List<Point> lp = new ArrayList<Point>(); //visit queue
                        lp.add(new Point(i,j));
                        int result = S;
                        for(int k=0;k<lp.size();++k){ //Notice: the size of queue maybe increase during the loop  
                            Point p = lp.get(k);
                            if(test(p.x,p.y,lp) == NS){ //once find the NS flag,stop checking
                                result = NS;
                                break;
                            }
                        }
                        for(int k=0;k<lp.size();++k){ //mark  all points in the current visit queue
                            Point p = lp.get(k);
                            mark[p.x][p.y] = result;
                        }
                    }
                }
            }
            for(int i=0;i<h;++i){ //flip all marked points
                char[] row = board[i];
                int[] mrow = mark[i];
                for(int j=0;j<w;++j){
                    char c = row[j];
                    if(c=='O' && mrow[j]==S){
                        row[j] ='X';
                    }
                }
            }
        }

    ====update====
    改進了一下,從邊開始掃描,找到所有邊上白字相鄰的節點即可解決問題。代碼如下:

    public class SurroundedRegions {

        private char[][] board;
        private int[][] mark;
        private int h;
        private int w;

        private static class Point {
            int x, y;

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

        private List<Point> extend(int i, int j) {
            List<Point> lp = new ArrayList<Point>();
            int[] nx = { i - 1, i, i, i + 1 };
            int[] ny = { j, j - 1, j + 1, j };
            for (int k = 0; k < 4; ++k) { // check the four directions
                int x = nx[k];
                int y = ny[k];
                if (x >= 0 && x < h && y >= 0 && y < w && board[x][y] == 'O' && mark[x][y] == 0) {
                    mark[x][y] = 1;
                    lp.add(new Point(x, y));
                }
            }
            return lp;
        }

        public void solve(char[][] board) {
            this.h = board.length;
            if (h <= 1) {
                return;
            }
            this.w = board[0].length;

            this.board = board;
            this.mark = new int[h][w];

            int x = 0, y = 0;
            int[] dxx = { 1, 0, -1, 0 };
            int[] dyy = { 0, 1, 0, -1 };

            for (int i = 0; i < 4; ++i) {
                int dx = dxx[i];
                int dy = dyy[i];
                int len = (i % 2 == 0) ? h : w;
                for (int j = 0; j < len-1; ++j) {
                    char c = board[x][y];
                    if (c == 'O' && mark[x][y] == 0) {
                        List<Point> vq = new ArrayList<Point>(); // visit queue
                        vq.add(new Point(x, y));
                        while (!vq.isEmpty()) {
                            Point p = vq.remove(vq.size() - 1);
                            mark[p.x][p.y] = 1;
                            vq.addAll(extend(p.x, p.y));
                        }
                    }
                    x += dx;
                    y += dy;
                }
            }

            for (int i = 0; i < h; ++i) { // flip all unmarked points
                char[] row = board[i];
                int[] mrow = mark[i];
                for (int j = 0; j < w; ++j) {
                    char c = row[j];
                    if (c == 'O' && mrow[j] == 0) {
                        row[j] = 'X';
                    }
                }
            }
        }
    }





    評論

    # re: 包圍的區域  回復  更多評論   

    2013-04-22 10:43 by cintana
    貌似太復雜了,為啥不直接掃描邊上的‘o'呢,一下就解決了。

    # re: 包圍的區域  回復  更多評論   

    2013-04-22 18:05 by 小明
    @cintana

    謝謝,確實,我想復雜了
    主站蜘蛛池模板: 亚洲综合伊人久久综合| 亚洲人色婷婷成人网站在线观看 | 日韩午夜理论免费TV影院| 无码成A毛片免费| 久久99免费视频| a级毛片毛片免费观看永久| 亚洲爆乳无码专区| 亚洲成在人天堂在线| 57pao一国产成永久免费| 免费一级毛片无毒不卡| 三年片在线观看免费西瓜视频| 国产va免费精品| 最近2019中文免费字幕在线观看| 久久久久久噜噜精品免费直播| 国产免费人成视频在线播放播 | 亚洲一区二区三区在线播放| 亚洲午夜精品一级在线播放放| 国产成人高清亚洲| 国产V亚洲V天堂无码| 精品亚洲成a人片在线观看| 国产成人亚洲精品| 美女免费精品高清毛片在线视| 亚洲精品黄色视频在线观看免费资源 | 国产精品免费看久久久| 四虎在线视频免费观看视频| 一级特黄aaa大片免费看| 伊人免费在线观看| 91视频国产免费| 亚洲乱码国产一区三区| 免费又黄又爽又猛的毛片| 午夜宅男在线永久免费观看网| 国产精品亚洲mnbav网站 | 亚洲中文字幕乱码熟女在线| 免费人成网站永久| 免费A级毛片无码无遮挡内射| 亚洲国产av一区二区三区| 亚洲国产成AV人天堂无码| 一级毛片不卡免费看老司机| 久久久久国色AV免费观看性色| 亚洲色精品88色婷婷七月丁香| 久久亚洲国产成人影院|