Почему мой алгоритм не работает для горизонта манхэттена от codility
Тренировочные задания выполняю из чести. Я закончил со StoneWall со скоростью 100/100, но я застрял в основной идее проблемы горизонта Манхэттена в этой задаче. Задача описана здесь https://app.codility.com/programmers/task/stone_wall/
Когда я впервые прочитал эту задачу, я понял, что мне нужно просто посчитать минимальное количество каменных блоков, чтобы построить стену. Нет никаких объяснений, как можно расширять блоки и т. Д. (Вероятно, предполагается, что я должен знать это заранее. Но я никогда не работал с такой проблемой). Основываясь на моем понимании этой проблемы, я реализовал следующий алгоритм (как оказалось, неправильный)
public int solution(final int[] H)
{
if (H.length == 1)
{
return 1;
}
int blocks = 0;
int first = 0;
for (int i = 1; i <= H.length; i++)
{
if (i == H.length || H[first] > H[i])
{
for (int k = first; k < i; k++)
{
if (H[k] != 0)
{
for (int t = k + 1; t < i && H[k] <= H[t]; t++)
{
if (H[t] >= H[k])
{
H[t] = H[t] - H[k];
}
else
{
break;
}
}
blocks++;
}
}
first = i;
}
}
return blocks;
}
Приведенный выше код отлично подходит для простых небольших массивов. Например, {8, 8, 5, 7, 9, 8, 7, 4, 8}. Очевидно, это провальное выступление. Я хотел запустить это, чтобы понять, что я на правильном пути. Но он возвращает неверные результаты, например, для большого массива со значениями в пределах 1 ... 20. Проблема в том, что я не понимаю основную идею процесса строительства стены, поэтому я не могу воспроизвести ее на своем локальном компьютере.
Затем я немного исследовал и нашел это решение на codility https://codility.com/media/train/solution-stone-wall.pdf Он говорит, что
The intuition is that by extending each stone block to the ground, we obtain a set of
buildings forming the given skyline.
Я подумал, что это ключ к разгадке (я должен просто складывать меньшие блоки поверх более крупных). Но потом я взглянул на фигуры с возможным расположением блоков, и это снова меня сбило с толку.
Наконец, я реализовал его, используя второе изображение выше, и он работает хорошо (100% кодируемость).
public int solution2(final int[] H)
{
if (H.length == 1)
{
return 1;
}
int blocks = 0;
final ArrayDeque<Integer> stack = new ArrayDeque<Integer>();
stack.push(H[0]);
for (int i = 1; i < H.length; i++)
{
while (stack.size() > 0 && stack.peek() > H[i])
{
stack.pop();
blocks++;
}
if (stack.isEmpty() || stack.peek() < H[i])
{
stack.push(H[i]);
}
}
return blocks + stack.size();
}
Может кто-нибудь объяснить мне, пожалуйста, почему первый алгоритм не работает для этой задачи?