Super clean Java code
\nclass Solution {\n    int n, m;\n    char[][] grid;\n    int[][] dirs = new int[][] {\n        {1, 0}, {0, 1}, {-1, 0}, {0, -1}\n    };\n    public int minPus
```\nclass Solution {\n    int n, m;\n    char[][] grid;\n    int[][] dirs = new int[][] {\n        {1, 0}, {0, 1}, {-1, 0}, {0, -1}\n    };\n    public int minPushBox(char[][] grid) {\n        n = grid.length;\n        m = grid[0].length;\n        this.grid = grid;\n        int[] box = new int[2], target = new int[2], player = new int[2];\n        findLocations(box, target, player);\n\n        Queue<int[]> q = new LinkedList();\n        q.offer(new int[]{box[0], box[1], player[0], player[1]});\n        boolean[][][] visited = new boolean[n][m][4]; // for 4 directions\n        int steps = 0;\n        while(!q.isEmpty()) {\n            int size = q.size();\n            while(size-- > 0) {\n                int[] cur = q.poll();\n                if(cur[0] == target[0] && cur[1] == target[1]) return steps;\n                for(int i = 0; i < 4; i++) {\n                    int[] newPlayerLoc = new int[]{cur[0] + dirs[i][0], cur[1] + dirs[i][1]};\n                    int[] newBoxLoc = new int[]{cur[0] - dirs[i][0], cur[1] - dirs[i][1]};\n                    if(visited[cur[0]][cur[1]][i] || isOutOfBounds(newPlayerLoc, newBoxLoc) || !isReachable(newPlayerLoc, cur)) continue;\n                    visited[cur[0]][cur[1]][i] = true;\n                    q.offer(new int[]{newBoxLoc[0], newBoxLoc[1], cur[0], cur[1]});\n                }\n            }\n            steps++;\n        }\n        \n        return -1;\n        \n    }\n    \n    public boolean isReachable(int[] targetPlayerLoc, int[] cur) {\n        boolean[][] visited = new boolean[n][m];\n        visited[cur[0]][cur[1]] = true;\n        visited[cur[2]][cur[3]] = true;\n\n        Queue<int[]> q = new LinkedList();\n        q.offer(new int[]{cur[2], cur[3]});\n        while(!q.isEmpty()) {\n            int[] playerLoc = q.poll();\n            if(playerLoc[0] == targetPlayerLoc[0] && playerLoc[1] == targetPlayerLoc[1]) return true;\n            for(int[] d: dirs) {\n                int x = playerLoc[0] + d[0];\n                int y = playerLoc[1] + d[1];\n                if(isOutOfBounds(x, y) || visited[x][y]) continue;\n                visited[x][y] = true;\n                q.offer(new int[]{x, y});\n            } \n        }\n        return false;\n    }\n    \n    public boolean isOutOfBounds(int[] player, int[] box) {\n        return isOutOfBounds(player[0], player[1]) || isOutOfBounds(box[0], box[1]);\n    }\n    \n    public boolean isOutOfBounds(int x, int y) {\n        return (x < 0 || y < 0 || x == n || y == m || grid[x][y] == \'#\');\n    }\n    \n    public void findLocations(int[] box, int[] target, int[] player) {\n        boolean p = false, t = false, b = false;\n        for(int i = 0; i < n; i++) {\n            for(int j = 0; j < m; j++) {\n                if(grid[i][j] == \'S\') {\n                    player[0] = i;\n                    player[1] = j;\n                    p = true;\n                } else if(grid[i][j] == \'T\') {\n                    target[0] = i;\n                    target[1] = j;\n                    t = true;\n                } else if(grid[i][j] == \'B\') {\n                    box[0] = i;\n                    box[1] = j;\n                    b = true;\n                }\n                \n                if(p && b && t) return; // found all\n            }\n        }\n    }\n}\n```
[]