I'm not sure what @aceofspades means by maximum time or minimum time (in the title it says maximum time and in the description it says we have to determine the minimum time). What I understand is that find the time that till all fresh oranges get rotten (if possible).

Complexity is O(M x N) because we only visit each cell once. Fresh oranges that got infected will be visited twice.

int timeToRot = 0;
public void problemTimeToRotOrange() {
int[][] farm = new int[][] {{1, 1, 1, 1, 0},
{0, 1, 0, 1, 1},
{2, 1, 1, 0, 2},
{2, 1, 1, 0, 0}};
// int[][] farm = new int[][] {{1, 0, 1, 1, 0},
// {0, 1, 0, 1, 1},
// {2, 1, 1, 0, 2},
// {2, 1, 1, 0, 0}};
timeToRotFarm(farm);
// for(int i = 0; i < farm.length; i++) {
// for(int j = 0; j < farm[0].length; j++)
// System.out.print(farm[i][j] + " ");
// System.out.println();
// }
for(int i = 0; i < farm.length; i++) {
for(int j = 0; j < farm[0].length; j++) {
if(farm[i][j] == 1) {
timeToRot = -1;
break;
}
}
}
System.out.println(timeToRot);
}
private void timeToRotFarm(int[][] farm) {
boolean[][] visited = new boolean[farm.length][farm[0].length];
for(int i = 0; i < farm.length; i++) {
for(int j = 0; j < farm[0].length; j++) {
if(farm[i][j] == 2)
rotCrop(farm, i, j, visited);
}
}
}
private void rotCrop(int[][] farm, int i, int j, boolean[][] visited) {
if(i < 0 || i == farm.length || j < 0 || j == farm[0].length || farm[i][j] == 0 || visited[i][j])
return;
if(farm[i][j] == 2) {
visited[i][j] = true;
// move north
rotCrop(farm, i - 1, j, visited);
// move east
rotCrop(farm, i, j + 1, visited);
// move south
rotCrop(farm, i + 1, j, visited);
// move west
rotCrop(farm, i, j - 1, visited);
return;
} else if(farm[i][j] == 1){
// farm[i][j] = 1, it's fresh so infect it
farm[i][j] = 2;
timeToRot++;
rotCrop(farm, i, j, visited);
}
}