Capture Regions on Board

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.

Input Format:

    First and only argument is a N x M character matrix A

Output Format:

    make changes to the the input only as matrix is passed by reference.

Constraints:

    1 <= N,M <= 1000

For Example:

Input 1:
    A = [ [X, X, X, X],
          [X, O, O, X],
          [X, X, O, X],
          [X, O, X, X] ]
Output 1:
    After running your function, the board should be:
    A = [ [X, X, X, X],
          [X, X, X, X],
          [X, X, X, X],
          [X, O, X, X] ]
Explanation:
    O in (4,2) is not surrounded by X from below.
Method:

Use DFS to replace all O's connected to the boarders to #, then replace all other O's to X. and then replace # back to O.

Solution:

Time: O(mn + E)

public class Solution {
    public void solve(ArrayList<ArrayList<Character>> a) {
       int m = a.size();
       int n = a.get(0).size();
       boolean[][] visited = new boolean[m][n];
       for (int j = 0; j < n; j ++) {
           if (a.get(0).get(j) == 'O') {
               dfs(a, 0, j, visited);
           }
       }
       for (int i = 1; i < m; i ++) {
           if (a.get(i).get(n - 1) == 'O') {
               dfs(a, i, n - 1, visited);
           }
       }
       for (int j = n - 2; j >= 0; j --) {
           if (a.get(m - 1).get(j) == 'O') {
               dfs(a, m - 1, j, visited);
           }
       }
       for (int i = m - 2; i >= 1; i --) {
           if (a.get(i).get(0) == 'O') {
               dfs(a, i, 0, visited);
           }
       }
       for (int i = 0; i < m; i ++) {
           for (int j = 0; j < n; j ++) {
               if (a.get(i).get(j) == 'O') {
                   a.get(i).set(j, 'X');
               }
               if (a.get(i).get(j) == '#') {
                   a.get(i).set(j, 'O');
               }
           }
       }
    }
    
    private void dfs(ArrayList<ArrayList<Character>> a, int x, int y, boolean[][] visited) {
        if (visited[x][y]) return;
        visited[x][y] = true;
        int m = a.size();
        int n = a.get(0).size();
        int[] dx = new int[]{-1,0,1,0};
        int[] dy = new int[]{0,1,0,-1};
        if (a.get(x).get(y) == 'O') {
            a.get(x).set(y, '#');
            for (int i = 0; i < 4; i ++) {
                int nX = x + dx[i];
                int nY = y + dy[i];
                if (nX >= 0 && nX < m && nY >= 0 && nY < n) {
                    dfs(a, nX, nY, visited);
                }
            }
        }
    }
}