1. 程式人生 > >【LeetCode-面試算法經典-Java實現】【130-Surrounded Regions(圍繞區域)】

【LeetCode-面試算法經典-Java實現】【130-Surrounded Regions(圍繞區域)】

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(圍繞區域)】