<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

    謝謝,確實,我想復雜了
    主站蜘蛛池模板: 亚洲AV无码之日韩精品| 成人午夜大片免费7777| 亚洲综合av永久无码精品一区二区| 亚洲精品国产综合久久久久紧| 成人A级毛片免费观看AV网站| 激情内射亚洲一区二区三区爱妻| 中文字幕免费在线看线人| 亚洲一级视频在线观看| 2021国产精品成人免费视频| 亚洲国产品综合人成综合网站| 69式国产真人免费视频| 四虎必出精品亚洲高清| 日本一道本高清免费| 疯狂做受xxxx高潮视频免费| 国产91精品一区二区麻豆亚洲| jzzjzz免费观看大片免费| 亚洲成色www久久网站夜月| 亚洲免费在线播放| 亚洲国产精品久久网午夜 | 久久精品免费观看| 亚洲明星合成图综合区在线| 午夜免费福利在线| 视频免费1区二区三区| 亚洲AV日韩精品久久久久| 成年美女黄网站色大免费视频| 美景之屋4在线未删减免费| 亚洲人成人无码网www电影首页| 亚洲黄色免费网站| 美国毛片亚洲社区在线观看| 在线A亚洲老鸭窝天堂| 免费精品国偷自产在线在线| 午夜在线亚洲男人午在线| 国产成人精品日本亚洲| 成人片黄网站色大片免费| 中文毛片无遮挡高清免费| 亚洲欧洲日本天天堂在线观看| 日韩激情淫片免费看| APP在线免费观看视频| 在线观看日本亚洲一区| 亚洲永久精品ww47| 女人被男人躁的女爽免费视频|