Почему мой алгоритм не работает для горизонта манхэттена от 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.

Я подумал, что это ключ к разгадке (я должен просто складывать меньшие блоки поверх более крупных). Но потом я взглянул на фигуры с возможным расположением блоков, и это снова меня сбило с толку.

  1. 2.

Наконец, я реализовал его, используя второе изображение выше, и он работает хорошо (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();
    }

Может кто-нибудь объяснить мне, пожалуйста, почему первый алгоритм не работает для этой задачи?

0 ответов

Другие вопросы по тегам