字節跳動面試算法題【Surrounded Regions】

前言

前陣子參加了,字節跳動的面試,面試官給出了一道算法題,題目雖然不難,但不知道怎麼,當時也沒作出來,如今回頭再作一次。該算法題其實就是leetcode上的130. Surrounded Regions.javascript

題目描述

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.
複製代碼
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
複製代碼

解題思路

思路分析

在面試時,我一開始的思路是直接找出被包圍的O,可是在後期實現的時候發現這種方式雖然可行,可是實現起來賊麻煩,判斷特別多,很容易出錯。後來,面試官提示我從側面思考,找到全部未被X包圍的O.java

  1. O要被包圍的條件是上下左右都爲X,由此咱們能夠推出邊界上的O確定不會被包圍。被包圍的O只可能出如今內部。python

  2. 找到全部未被包圍的O,而後將剩下的O所有變爲1.面試

  3. 那麼如何找到全部未被包圍的O呢?經過前面的分析,咱們能夠知道邊界上的O確定是未被包圍的,因此,咱們能夠從這裏入手。到了這裏,咱們就很容易想到使用floodfill算法。算法

代碼實現

針對上面的例子而言,要找出全部被包圍的O,對每個節點的訪問是必不可免的。咱們很容易想到雙重循環:數組

for(let i=0;i<grid.length;i++){
    for(let j=0;j<grid[i].length;j++){
        // do something on grid[i][j]
    }
}
複製代碼

經過上面的分析,咱們知道不被包圍的O確定是出如今邊界的。bash

咱們簡單來舉幾個例子:ui

X X O X              X X X X            X X O X
一  O O O X       二     X O O X       三   X 0 0 X
    X O X X              X O O X            X 0 0 X
    X O X X              X X X X            X X X X
複製代碼

對於來講,當咱們訪問到grid[0][2]的時候,咱們發現grid[0][2]=='O',基於此,咱們在這裏開始採用floodfill算法。spa

算法思路以下:code

  • 若是grid[i][j]==='O',咱們首先要用一種標識表示,當前位置咱們已經訪問過。
  • 爲了到達標識的能夠有兩種思路,一種是用另外一個和grid規模形狀相同的二維數組對每個元素是否訪問過作標識,另外一種是在原地作標識。
    • 使用二維數組作標識。
    let hasVisited = new Array(grid.length).fill(new Array(grid[0].length).fill(0))
    ...// some logics
    if(grid[i][j]==='O' && hasVisited==0){ //當前節點爲`O`,並且以前未被訪問過
        hasVisited==1
    }
    複製代碼
    • 原地標識,將已經訪問過的元素修改成*,這樣咱們就知道咱們以前有沒有訪問過了。
    if(grid[i][j]=='O'){
        grid[i][j]='*'
    }
    複製代碼
  • grid[i][j]=='O'的位置開始floodfill算法。floodfill的算法其實很簡單,就是從當前位置開始,向上、下、左、右四個位置開始進行染色,若是該位置是O,咱們一樣將其標識爲*, 對於上面的例子來講,最終結果爲:
X X * X       X X X X       X X * X
一  * * * X   二  X O O X  三   X * * X
    X * X X       X O O X       X * * X
    X * X X       X X X X       X X X X
複製代碼

咱們發現第二個例子並無發生變化,若是O要想不被包圍,那麼其邊界上必定要有O.

for(let i=0;i<grid.length;i++){
    for(let j=0;j<grid[i].length;j++){
        // do something on grid[i][j]
        if(i===0 || i===grid.length-1 || j===0 || j===grid[i].length){
            if(grid[i][j]==='O'){//floodfill
                dfs(grid,i,j)
            }
        }
    }
}

複製代碼

解題代碼:

javascript

var solve = function (board) {
    let m = board.length;
    let n = board[0] ? board[0].length : 0
    if (m === 0 || n === 0) {
        return;
    }
    let map = [[-1, 0], [0, 1], [1, 0], [0, -1]]
    function dfs(board, x, y) {
        if (x < 0 || x >= m || y < 0 || y >= n || board[x][y] !== 'O' ) {// out of boundary
            return;
        }
        if(board[x][y] == 'O'){
            board[x][y] = '*'
             for (let i = 0; i < 4; i++) {
            dfs(board, x + map[i][0], y + map[i][1])
            }
        }
        // return;
    }
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if ((i == 0 || i == m - 1 || j == 0 || j == n - 1) && board[i][j] === 'O') {
                    dfs(board, i, j) 
            }
        }
    }
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            board[i][j] = board[i][j] === '*'?'O':'X'
        }
    }
};

複製代碼

python3

class Solution:
    def solve(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        directions = [[-1, 0], [1, 0], [0, 1], [0, -1]]
        m = len(board)
        if m == 0:
            return;
        n = len(board[0])
        if n == 0:
            return;

        def dfs(board, x, y):
            if(x < 0 or x >= m or y < 0 or y >= n or board[x][y] != 'O'):
                return
            if board[x][y] == 'O':
                board[x][y] = '*'
                for i in range(4):
                    dfs(board, x+directions[i][0], y+directions[i][1])
        for i in range(m):
            for j in range(n):
                if(i == 0 or i == m-1 or j == 0 or j == n-1) and board[i][j] == 'O':
                    dfs(board, i, j)

        for i in range(m):
            for j in range(n):
                board[i][j] = 'O' if board[i][j]=='*' else 'X'
                    
複製代碼

java

class Solution {
    private int m,n;
    private int[][] map={{-1,0},{0,1},{1,0},{0,-1}};
    public void solve(char[][] board) {
        m = board.length;
        if(m==0){
            return;
        }
        n = board[0].length;
        if(n==0){
            return;
        }
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                 if (i == 0 || i == m - 1 || j == 0 || j == n - 1){
                      if(board[i][j]=='O'){
                    dfs(board,i,j);
                    }
                 }
               
            }    
        }
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                board[i][j]=board[i][j]=='*'?'O':'X';
            }    
        }
    }
    private void dfs(char[][] board,int x,int y){
        if(x<0 || x>=m || y<0 || y>=n || board[x][y]!='O'){
            return;
        }
        if(board[x][y]=='O'){
            board[x][y]='*';
            for(int i=0;i<4;i++){
                dfs(board,x+map[i][0],y+map[i][1]);
            }
        }
    }
}
複製代碼
相關文章
相關標籤/搜索