10 ms solution, BFS with some comments
\nclass Solution {\n    public int minPushBox(char[][] grid) {\n        if(grid == null)\n            return 0;\n        \n        int row = grid.length;\n     
```\nclass Solution {\n    public int minPushBox(char[][] grid) {\n        if(grid == null)\n            return 0;\n        \n        int row = grid.length;\n        int col = grid[0].length;\n        int[] target = null;\n        int[] box = null;\n        int[] player = null;\n        \n        for(int i=0; i < row; i++) {\n            for(int j=0; j < col; j++) {\n                if(grid[i][j] == \'T\')\n                    target = new int[] {i, j};\n                if(grid[i][j] == \'S\')\n                    player = new int[] {i, j};\n                if(grid[i][j] == \'B\')\n                    box = new int[] {i, j};                \n            }\n        }\n        \n        Queue<int[]> q = new ArrayDeque<>();\n        Set<List<Integer>> visited = new HashSet<>();\n\n        //Add player and box current location to queue as state\n        q.offer(new int[] {player[0], player[1], box[0], box[1]});\n        visited.add(new ArrayList<>(Arrays.asList(player[0], player[1], box[0], box[1])));        \n        \n        int[][] dirs = new int[][] {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};\n        int push = 0;\n        \n        while(!q.isEmpty()) {\n            int size = q.size();\n            \n            for(int i=0; i < size; i++) {\n                int[] state = q.poll();\n                if(state[2] == target[0] && state[3] == target[1])\n                    return push;\n                \n                for(int[] dir: dirs) {\n                    //player need to be here\n                    int pX = state[2] - dir[0];\n                    int pY = state[3] - dir[1];\n                    \n                    //To push box in this direction\n                    int bX = state[2] + dir[0];\n                    int bY = state[3] + dir[1];\n                    if(pX < 0 || pX >= row || pY < 0 || pY >= col || \n                       bX < 0 || bX >= row || bY < 0 || bY >= col ||\n                       grid[bX][bY] == \'#\' || grid[pX][pY] == \'#\' ||\n                       visited.contains(new ArrayList<>(Arrays.asList(state[2], state[3], bX, bY))) || \n                       //player can reach the push location given current box location\n                       !canReach(state[0], state[1], grid, pX, pY, state[2], state[3])) \n                        continue;\n                    \n                    //box location updated and player location updated to last box location                    \n                    q.offer(new int[] {state[2], state[3], bX, bY}); \n                    visited.add(new ArrayList<>(Arrays.asList(state[2], state[3], bX, bY)));                    \n                }\n            }\n            push++;\n            \n        }\n                \n        return -1;\n        \n    }\n    \n    \n    public boolean canReach(int x, int y, char[][] grid, int tX, int tY, int bX, int bY) {\n        Queue<int[]> q = new ArrayDeque<>();\n        \n        q.offer(new int [] {x, y});\n        int[][] dirs = new int[][] {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};\n        boolean visited[][] = new boolean[grid.length][grid[0].length];\n        while(!q.isEmpty()) {\n            int size = q.size();\n            \n            for(int i=0; i < size; i++){\n                int[] state = q.poll();\n                \n                if(state[0] == tX && state[1] == tY)\n                    return true;\n                \n                for(int[] dir: dirs) {\n                    int newX = state[0] + dir[0];\n                    int newY = state[1] + dir[1];\n                    \n                    if(newX < 0 || newY < 0 || \n                       newX >= grid.length || newY >= grid[0].length || \n                       visited[newX][newY] || grid[newX][newY] == \'#\' || \n                       (newX == bX && newY == bY))\n                        continue;\n                    q.offer(new int[] {newX, newY});\n                    visited[newX][newY] = true;\n                }\n                \n                \n            }\n            \n        }\n        \n        return false;\n\n    }\n    \n}\n\n```
[]