Как реализовать обход матрицы для подсчета кораблей по строкам и столбцам?
Что проверяют
Умеете ли вы уточнить условие до кода: считать клетки с кораблями или сами корабли. Затем смотрят на аккуратность обхода и сложность. Следом обычно спрашивают, что изменится, если корабли могут касаться друг друга или быть изогнутыми.
Как отвечать
Сначала вопросы: чем обозначен корабль (int 1 или символ), могут ли корабли соприкасаться, прямые ли они, бывает ли матрица пустой или рваной.
Если нужно число занятых клеток в каждой строке и столбце, хватает одного прохода: rows[i]++ и cols[j]++ в одном двойном цикле. Время O(n·m), дополнительная память O(n + m). Идите по строкам: в Java двумерный массив это массив ссылок на отдельные массивы, и проход по столбцам прыгает между ними, теряя кэш.
Если нужны корабли в классическом «морском бое» (прямые, не касаются), клетку считают началом корабля, когда она занята, а сверху и слева пусто:
if (b[i][j] == 1
&& (i == 0 || b[i - 1][j] != 1)
&& (j == 0 || b[i][j - 1] != 1)) ships++;Один проход, O(1) дополнительной памяти, матрица не меняется. Чтобы разложить корабли по строкам и столбцам, тем же приёмом считают горизонтальные отрезки от двух клеток в строках и вертикальные в столбцах, а однопалубные учитывают один раз.
Если корабли произвольной формы или касаются, это уже поиск компонент связности: BFS на ArrayDeque с массивом visited или система непересекающихся множеств.
Где спотыкаются
Не уточняют условие и считают клетки, хотя спрашивали корабли. Четырёхпалубный корабль в строке тогда превращается в четыре.
Берут matrix[0].length без проверки. На пустом массиве это ArrayIndexOutOfBoundsException, а в рваном массиве строка короче первой даёт выход за границы на середине обхода.
Пишут рекурсивный DFS для заливки. На поле 1000×1000 со сплошной областью глубина рекурсии упирается в StackOverflowError, поэтому обход делают итеративным.