【LeetCode-面試算法經典-Java實現】【130-Surrounded Regions(圍繞區域)】
阿新 • • 發佈:2017-06-10
pos apt pub iso all 左面 ons || title
【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】
【LeetCode-面試算法經典-Java實現】【130-Surrounded Regions(圍繞區域)】