【LeetCode-面试算法经典-Java实现】【130-Surrounded Regions(环绕区域)】

【130-Surrounded Regions(环绕区域)】


【LeetCode-面试算法经典-Java实现】【所有题目目录索引】

原题

  Given a 2D board containing ‘X‘ and ‘O‘, capture all regions surrounded by ‘X‘.

  A region is captured by flipping all ‘O‘s into ‘X‘s in that surrounded region.

  For example,

X X X X
X O O X
X X O X
X O X X

  After running your function, the board should be:

X X X X
X X X X
X X X X
X O X X

题目大意

  一个二维网格,包含’X’与’O’,将所以被X包围的O区域用X替代,返回替代后后结果。

解题思路

  采用广度优先遍历的方式,(也可以采用尝试深度优先的方式(会有栈溢出)),标记出所有的被包围的点,剩下的就是不被包围的点

代码实现

算法实现类

import java.util.LinkedList;
import java.util.List;

public class Solution {
    ////////////////////////////////////////////////////////////////////////////////////////////////
    // 下面采用广度度优先遍历的方式,找出所有的【不】被包围的点
    ////////////////////////////////////////////////////////////////////////////////////////////////
    public void solve(char[][] board) {
        // 参数校验
        if (board == null || board.length < 1 || board[0].length < 1) {
            return;
        }

        boolean[][] visited = new boolean[board.length][board[0].length];
        // 广度优先搜索时外围一圈的元素
        List<Coordinate> round = new LinkedList<>();
        // 处理顶部行
        for (int col = 0; col < board[0].length; col++) {
            // 顶部行,并且点是O并且点未被访问过
            if (!visited[0][col] && board[0][col] == ‘O‘) {
                round.clear();
                round.add(new Coordinate(0, col));
                bfs(board, visited, round);
            }
        }

        // 处理底部行
        for (int col = 0; col < board[0].length; col++) {
            // 顶部行,并且点是O并且点未被访问过
            if (!visited[board.length - 1][col] && board[board.length - 1][col] == ‘O‘) {
                round.clear();
                round.add(new Coordinate(board.length - 1, col));
                bfs(board, visited, round);
            }
        }

        // 处理左边列
        for (int row = 1; row < board.length - 1; row++) {
            // 顶部行,并且点是O并且点未被访问过
            if (!visited[row][0] && board[row][0] == ‘O‘) {
                round.clear();
                round.add(new Coordinate(row, 0));
                bfs(board, visited, round);
            }
        }

        // 处理右边列
        for (int row = 1; row < board.length - 1; row++) {
            // 顶部行,并且点是O并且点未被访问过
            if (!visited[row][board[0].length - 1] && board[row][board[0].length - 1] == ‘O‘) {
                round.clear();
                round.add(new Coordinate(row, board[0].length - 1));
                bfs(board, visited, round);
            }
        }

        // 标记网格
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                // 如果未被访问过,有两种可能,第一是X点,第二是O点,O点一定是被X包围的
                // 此时将未访问过的点设置为X是正确的
                if (!visited[i][j]) {
                    board[i][j] = ‘X‘;
                }
            }
        }
    }

    /**
     * 深度优先,找不被包围的点
     *
     * @param board   二维网格
     * @param visited 访问标记数组
     * @param round   广度优先搜索时外围一圈的元素
     */
    public void bfs(char[][] board, boolean[][] visited, List<Coordinate> round) {
        Coordinate c;
        while (round.size() > 0) {
            c = round.remove(0);
            if (c.x >= 0 && c.x < board.length && c.y >= 0 && c.y < board[0].length && board[c.x][c.y] == ‘O‘ && !visited[c.x][c.y]) {
                visited[c.x][c.y] = true;
                round.add(new Coordinate(c.x - 1, c.y));
                round.add(new Coordinate(c.x, c.y + 1));
                round.add(new Coordinate(c.x + 1, c.y));
                round.add(new Coordinate(c.x, c.y - 1));
            }
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
    // 下面采用广度度优先遍历的方式,找出所有的被包围的点,并且标记会超时
    ////////////////////////////////////////////////////////////////////////////////////////////////
    public void solve2(char[][] board) {
        // 参数校验
        if (board == null || board.length < 1 || board[0].length < 1) {
            return;
        }

        boolean[][] visited = new boolean[board.length][board[0].length];

        // 广度优先搜索时外围一圈的元素
        List<Coordinate> round = new LinkedList<>();
        // 广度优先搜索进的所有元素
        List<Coordinate> all = new LinkedList<>();

        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (!visited[i][j] && board[i][j] == ‘O‘) {
                    // 广度优先搜索第一圈的元素
                    round.add(new Coordinate(i, j));
                    boolean result = bfs(board, visited, round, all);
                    // 一次搜索的所有O都在网格内,并且不在边界上
                    if (result) {
                        // 设置标记
                        for (Coordinate c : all) {
                            board[c.x][c.y] = ‘X‘;
                        }
                    }

                    // 清空元素
                    round.clear();
                    all.clear();
                }
            }
        }

    }

    /**
     * 广度优先遍历
     *
     * @param board   二维网格
     * @param visited 访问标记数组
     * @param round   广度优先搜索时外围一圈的元素
     * @param all     广度优先搜索进的所有元素
     * @return true点是O,点在网格内,并且不在边界上,如果点是X,总返回true
     */
    public boolean bfs(char[][] board, boolean[][] visited, List<Coordinate> round, List<Coordinate> all) {
        boolean result = true;
        int size = round.size();
        Coordinate c;
        while (size > 0) {
            size--;

            // 取队首元素
            c = round.remove(0);
            // 添加到遍历记录元素集合中
            all.add(c);
            // 标记已经被访问过了
            visited[c.x][c.y] = true;
            // 判断c是否是O内点
            result &= isInner(board, c.x, c.y);

            // c的上面一个点是否是O,并且没有访问过,满足就添加到round队列中
            if (isO(board, c.x - 1, c.y) && !visited[c.x - 1][c.y]) {
                round.add(new Coordinate(c.x - 1, c.y));
            }

            // c的右面一个点是否是O,并且没有访问过,满足就添加到round队列中
            if (isO(board, c.x, c.y + 1) && !visited[c.x][c.y + 1]) {
                round.add(new Coordinate(c.x, c.y + 1));
            }

            // c的下面一个点是否是O,并且没有访问过,满足就添加到round队列中
            if (isO(board, c.x + 1, c.y) && !visited[c.x + 1][c.y]) {
                round.add(new Coordinate(c.x + 1, c.y));
            }

            // c的左面一个点是否是O,并且没有访问过,满足就添加到round队列中
            if (isO(board, c.x, c.y - 1) && !visited[c.x][c.y - 1]) {
                round.add(new Coordinate(c.x, c.y - 1));
            }
        }

        if (round.size() > 0) {
            return bfs(board, visited, round, all) && result;
        } else {
            return result;
        }

    }

    /**
     * 判断点在二维风格内部,并且不在边界上
     *
     * @param board 二维网格
     * @param x     横坐标
     * @param y     纵坐标
     * @return true是
     */
    public boolean isInner(char[][] board, int x, int y) {
        return x > 0 && x < board.length - 1 && y > 0 && y < board[0].length - 1;
    }

    /**
     * 判断点是否是O
     *
     * @param board 二维网格
     * @param x     横坐标
     * @param y     纵坐标
     * @return true是
     */
    public boolean isO(char[][] board, int x, int y) {
        return x >= 0 && x < board.length && y >= 0 && y < board[0].length && board[x][y] == ‘O‘;
    }

    /**
     * 坐标对象
     */
    public static class Coordinate {
        private int x;
        private int y;

        public Coordinate() {
        }

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

        @Override
        public String toString() {
            return "(" + x + ", " + y + ")";
        }
    }
}

评测结果

  点击图片,鼠标不释放,拖动一段位置,释放后在新的窗口中查看完整图片。

特别说明

欢迎转载,转载请注明出处【http://blog.csdn.net/derrantcm/article/details/47678211

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 17:35:54

【LeetCode-面试算法经典-Java实现】【130-Surrounded Regions(环绕区域)】的相关文章

130. Surrounded Regions(周围区域问题 广度优先)(代码未完成!!)

Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'. A region is captured by flipping all 'O's into 'X's in that surrounded region. For example, X X X X X O O X X X O X X O X X After running your function, th

【LeetCode-面试算法经典-Java实现】【139-Word Break(单词拆分)】

[139-Word Break(单词拆分)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words. For example, given s = "leetcode", di

【LeetCode-面试算法经典-Java实现】【107-Binary Tree Level Order Traversal II(二叉树层序遍历II)】

[107-Binary Tree Level Order Traversal II(二叉树层序遍历II)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root). For example

【LeetCode-面试算法经典-Java实现】【064-Minimum Path Sum(最小路径和)】

[064-Minimum Path Sum(最小路径和)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. Note: You can only move either

【LeetCode-面试算法经典-Java实现】【056-Merge Intervals(区间合并)】

[056-Merge Intervals(区间合并)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a collection of intervals, merge all overlapping intervals. For example, Given [1,3],[2,6],[8,10],[15,18], return [1,6],[8,10],[15,18]. 题目大意 给定一个区间集合,合并有重叠的区间. 解题思路 先对区间进行排序.按開始

【LeetCode-面试算法经典-Java实现】【066-Plus One(加一)】

[066-Plus One(加一)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given a non-negative number represented as an array of digits, plus one to the number. The digits are stored such that the most significant digit is at the head of the list. 题目大意 给定一个用数组表示的一个数,

【LeetCode-面试算法经典-Java实现】【067-Add Binary(二进制加法)】

[067-Add Binary(二进制加法)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given two binary strings, return their sum (also a binary string). For example, a = "11" b = "1" Return "100" 题目大意 给定两个二进制的字符串,返回它们的和,也是二进行制字符串. 解题思路 先将对应的两个二进制字符串

【LeetCode-面试算法经典-Java实现】【054-Spiral Matrix(螺旋矩阵)】

[054-Spiral Matrix(螺旋矩阵)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order. For example, Given the following matrix: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ]

【LeetCode-面试算法经典-Java实现】【033-Search in Rotated Sorted Array(在旋转数组中搜索)】

[033-Search in Rotated Sorted Array(在旋转数组中搜索)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). You are given a target value to search.