zoukankan      html  css  js  c++  java
  • 130. Surrounded Regions

    一、题目

      1、审题

      

      2、分析

        给出一个二维数组,数组中只包含字符 'O'、‘X', 将数组中被 'X' 包围的 'O' 全部换成 'X'。(其中紧邻边界不算包围)

    二、解答

      1、思路: 

        方法一、

          ①、将紧挨着棋盘边缘的 "O'" 或者与边缘的 "O" 连通的 “O” 全部换成 “1“;

          ②、将剩下的 O 全部换成 X,将 “1” 全部换成 “O“;

        public void solve(char[][] board) {
            int rows = board.length;
            if(rows < 3)
                return;
            int cols = board[0].length;
            if(cols < 3)
                return;
            
            for (int row = 0; row < rows; row++) {
                check(board, row, 0, rows, cols); // 第一列的每个元素
                check(board, row, cols - 1, rows, cols); // 最后一列的每个元素
            }
            
            for (int j = 1; j < cols - 1; j++) {
                check(board, 0, j, rows, cols);    // 第一行 (除了第一个、最后一个元素)
                check(board, rows - 1, j, rows, cols);  // 最后一行
            }
            
            for(int i = 0; i < rows; i++) {
                for(int j = 0; j < cols; j++) {
                    if(board[i][j] == 'o')
                        board[i][j] = 'x';
                    if(board[i][j] == '1')
                        board[i][j] = 'o';
                    
                    System.out.print(board[i][j]);
                }
                System.out.println();
            }
        }
        
    
        void check(char[][] board, int row, int col, int rows, int cols) {
            
            if(board[row][col] == 'o') {
                board[row][col] = '1';
                if(row > 1)
                    check(board, row - 1, col, rows, cols);
                if(col > 1)
                    check(board, row, col - 1, rows, cols);
                if(row < rows - 1)
                    check(board, row + 1, col, rows, cols);
                if(col < cols - 1)
                    check(board, row, col + 1, rows, cols);
            }
        }
        

        方法二、

          使用 Union Find(并查集) 。

          ①、采用并查集将所有边界的值为 ‘O’ 的节点与并查集中一个特殊值 oRoot 合并在同一集合中,且 oRoot 作为他们的头结点。

          ②、将非边界的值为 ‘O’ 的节点与该节点上下左右值为 ‘O’ 的节点进行合并。

          ③、遍历数组所有元素,若值为 ‘O’,判断是否和 oRoot 是同一集合,若不是,则元素值改为 'X',否则不变化。

    public void solve(char[][] board) {
            
            if (board == null || board.length == 0 || board[0].length == 0)
                return;
            
            int rows = board.length;
            int cols = board[0].length;
            int oRoot = rows * cols;
            
            initUnionFind(rows * cols);
            
            for(int i = 0; i < rows; i++) {
                for (int j = 0; j < cols; j++) {
                    if(board[i][j] == 'X')
                        continue;
                    
                    int cur = i * cols + j;
                    if(i == 0 || i == rows - 1 || j == 0 || j == cols - 1) {    
                        union(cur, oRoot); // 将边界中值为 ’O‘ 的节点全部 并到 oRoot 所在集合中
                    }
                    else {
                        // 非边界的值为 ’O‘ 节点与  上下左右  值为 'O'的节点合并。
                        if(j + 1 < cols && board[i][j + 1] == 'O')
                            union(cur, i * cols + j + 1);
                        if(j - 1 >= 0 && board[i][j - 1] == 'O')
                            union(cur, i * cols + j - 1);
                        if(i + 1 < rows && board[i + 1][j] == 'O')
                            union(cur, (i+1) * cols + j);
                        if(i - 1 >= 0 && board[i - 1][j] == 'O')
                            union(cur, (i - 1) * cols + j);
                    }
                }
            }
            for (int i = 0; i < rows; i++) {
                for (int j = 0; j < cols; j++) {
                    if(board[i][j] == 'O' && find(i * cols + j) != oRoot)
                        board[i][j] = 'X';
                    
                    System.out.print(board[i][j] + ", " );
                }
                System.out.println();
            }
        }
        
        int[] s;
        int[] rank;
    
        // 找到根节点
        private int find(int p) {
            
            while(s[p] != p)
                p = s[p];
            
            return p;
        }
    
        private void union(int p, int q) {
            
            int pRoot = find(p);
            int qRoot = find(q);
            
            if(pRoot == qRoot)    
                return;
            if(rank[pRoot] < rank[qRoot]) { //保证小的树在大的下面
                s[pRoot] = qRoot;
                rank[qRoot] += rank[pRoot];
            }
            else {
    //            if(rank[pRoot] == rank[qRoot])
    //                rank[pRoot]++;
                s[qRoot] = pRoot;
                rank[pRoot] += rank[qRoot];
            }
            
        }
    
        private void initUnionFind(int n) {
            s = new int[n + 1];
            rank = new int[n + 1];
            for(int i = 0; i <= n; i++)
                s[i] = i;
            rank[n] = n + 1;
        }
  • 相关阅读:
    BadUSB 利用
    java 将函数作为参数传递
    odoo12 修行提升篇之 常用的高阶函数 (二)
    odoo12 修行提升篇之 异步定时任务 (一)
    odoo12 修行基础篇之 利用kanban做分析 点击跳转分析模型列表 (九)
    odoo12 修行基础篇之 kanban (八)
    odoo12 修行基础篇之 记录批处理 (七)
    odoo12 修行基础篇之 列表的筛选和分组 (六)
    odoo12 修行基础篇之 添加记录编码 (五)
    odoo12 修行基础篇之 添加工作流和操作记录 (四)
  • 原文地址:https://www.cnblogs.com/skillking/p/9753813.html
Copyright © 2011-2022 走看看