Ответы пользователя по тегу Алгоритмы
  • Почему не проходит решение?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Ваша идея правильная - тут можно жадно удалять по k листьев, пока можно.

    Но ваша логика решения мне не понятна. Вам следует в каждой вершине поддерживать счётчик соседей листьев и их список. Далее, имейте очередь вершин с более чем k листьев рядом. Удаляйте k листьев. Если текущая стала листом (нужны счётчики для степени вершин), то добавьте её в список к единственному соседу.

    Чтобы не возиться с удалением соседей, помещайте вершины удаленными и при обходе списка соседей удаляйте их
    Ответ написан
  • Как реализовать дерево на основе связного списка?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Вообще, дерево и список не изоморфны друг другу. В дереве же есть иерархия. Дерево нельзя реализовать с помощью списка (одного).

    Возможно, вам надо хранить детей каждой вершины в виде связного списка (тогда у вас будет куча списков). Еще, популярный подход (фактически делающий то же самое) - это хранить в каждой вершине ссылку/указатель на первого ребенка и на следующего брата. Так все списки будут перемешаны в одну большую структуру. Но тут, правда, в отличии от связного списка, все равно есть 2 типа ссылок.
    Ответ написан
    2 комментария
  • Из какой коллекции можно быстро удалять элемент, но к ней применим бин. поиск?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    TreeSet.

    Там можно искать нужный вам элемент через floor или ceiling. Поиск и удаление, если создатели библиотеки в java хоть что-то слышали про алгоритмы и структуры данных, работают за логарифм.
    Ответ написан
    Комментировать
  • Чему будет равна сложность этого алгоритма?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Зависит от размеров item. Если они там каждый O(N) размера, то ваша догадка правильная: O(n^2 log n).

    Если же все item суммарно не превосходят N, то ответ O(N log N). Потому что если их размеры a_i, то у вас сумма ai log ai. log(ai) можно сверху ограничить log(N) и вынести за скобки и потом заменить сумму в скобках на N.
    Ответ написан
    1 комментарий
  • Как найти максимально похожий цвет?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Если скорость не особо важна, то просто пройдитесь по всем именным цветам (лучше, чтобы это был какой-то списко или массив, а не мап) и считайте какую-то метрику (например, сумма квадратов разности по каждому каналу отдельно). Из полученных чисел ищите минимум и выдавайте тот цвет, что ее дал.

    Если надо работать очень быстро, то надо представить ваши именные цвета как точки в трехмерном пространстве, построить kd-дерево или r-дерево и уже в нем искать ближайшую к запрошенной точку.
    Ответ написан
    5 комментариев
  • В чем моя ошибка в задаче?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    У вас правильная идея, что двух чисел в ответе всегда достаточно. Всегда можно выдать, например, n, n-1 и эти две операции покроют все позиции с 1 по n.

    Но вот случай, когда достаточно одного числа вы неправильно разобрали. Почему вы ищите самое большое простое число? Какой вообще смысл смотреть, что в позиции ans-1 стоит c?

    А еще ваш код выводит 0 неверно иногда.

    Вы, может, задачу неправильно поняли? Надо сделать так, что бы все позиции, в которых символы отличные от c, не делились бы на хотя бы одно число в вашем ответе.
    Ответ написан
    1 комментарий
  • Почему LCS алгоритм находит совпадение в конце последовательности?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Ваша рекурсия восстонавливает ответ в динамическом программировании в матрице.

    Построение матрицы менять не надо, оно просто считает оптимальную длину LCS. Вам надо отдавать приоритет переходам вверх (или влево) пока это возможно при восстановлении ответа.

    Но можно сделать простой хак - усеките ваш текст как можно короче, пока LCS все еще оптимального размера.

    Вам надо найти самое первое максимальное число в последней строке (или столбце, в зависимости от того в какой из входных строчек вы хотите как можно левее найти вхождение. Я не в курсе, что у вас за aCompareFunc).

    От этой позиции и запускайте ваш DoDiff вместо левой нижней ячейки матрицы.

    Значения максимума даже не надо искать, он будет в левом нижнем углу матрицы. Вам остается только циклом найти самое левое число в строке (столбце) равное последнему.

    Вам еще придется в конце зарепортить необходимое количество l3diffDeleted или l3diffAdded, чтобы восстановить усеченную часть.
    Ответ написан
    1 комментарий
  • Как в двоичном дереве поиска найти минимальный элемент, больший данного?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Надо, как в бинарном поиске - идти или в левое или в правое поддерево. Если пошли в левое поддерево, то надо проверить, что вернула рекурсивная функция - если там не было больших элементов, то надо вернуть значение в текущей вершине.
    Ответ написан
    3 комментария
  • Почему не получается найти подпоследовательность?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    У вас решение за O(MN), когда как можно за O(M log N).

    Вы говорите, что оно линейно, но вы выполняете линейное количество операций на каждый элемент массива b. Это медленно. Ваша проблема в том, что вы храните все индексы для каждого значения просто в списке и потом там наивно ищите первое вхождение больше данной границы. Можно список хранить в Set. Вот я не в курсе, умеет ли он, как C++-шный set искать первый элемент больше заданной границы. Если нет, то можно тупо хранить отсортированые списки индексов, тогда там можно будет делать бинпоиск.
    Ответ написан
    7 комментариев
  • Как сделать перебор всех значений строки определенной длины состоящей из цифр и букв?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Ну вот как вы прибавляете 1 к числу из 0..9 прибавляйте 1 к числу, где цифры могут быть 0..9 и a..z. Все z в конце замените на 0, следующий символ увеличте на 1 (если стало '9'+1, то Замените на 'a').
    Ответ написан
    Комментировать
  • Почему решение задачи неправильное?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    is_subsequence написана с ошибкой. Что у вас там за алгоритм? Почему вы считатете, что оно должно работать?

    Оно, например, не работает на тесте s="abc" t="zzzzzcba". Ваша реализация скажет, что abc является подпоследовательностью, хотя на самом деле - нет.

    Еще хочется отдельно привлечь внимание к гениальности кода:
    if (is_sub)
            return true;
        else
            return false;


    Он кажется мне немного перемудренным.
    Ответ написан
    1 комментарий
  • Почему быстрая сортировка Хоара медленнее пузырьковой?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Во-первых, quicksort медленне всяких пузырьков на маленьких числах. Это нормально. У него ассимптотика лучше - он сильно быстрее на больших числах. Но константа из-за сложности алгоритма хуже - поэтому на маленьких числах он и проигрывает пузырьку. Во всех библиотечных реализациях квиксорта (да и любой другой логарифмической сортировки) там есть проверка, что если чисел мало, то запускать пузырек или сортировку вставками.

    Увеличте размер сортруемых массивов до 100 000 или до миллиона и квиксорт должен стать быстрее.

    Во-вторых, ваша быстрая сортировка написана весьма неоптимально. Пузырек у вас сортирует сам массив на месте, когда как квиксорт постоянно создает новые массивы через конкатенацию. Возьмите нормальную реализацию и на 1000 элементах квиксорт уже станет быстрее пузырька.
    Ответ написан
    Комментировать
  • Найдите перестановку по её номеру в лексикографическом порядке. Total - кол-во элементов, К - номер перестановки. Как сократить время программы?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Вы генерируете перестановки по одной, пока не отсчитаете k. Это медленно, потому что k может быть очень большим. Перестановок-то n! - это дофига много.

    Надо генерировать ее сразу по номеру.

    Посмотрите на первый элемент. У первых (n-1)! перестановок там 1, у следующих (n-1)! - там 2, потом идет группа, начинающихся с 3 и т.д.

    Уже вы можете понять в какой группе искомая k-ая перестановка. Тупо floor(k/(n-1)!) (если нумерация с 0 и перестановок и групп). Фактически, формула для первого элемента - a[0] = (k-1)/(n-1)! + 1.

    Дальше вы можете выкинуть из рассмотрения первый элемент. Сфокусируйтесь на группе с заданным известным первым элементом. Какой номер искомая перестановка имеет среди этих (n-1)!? Надо из k вычесть количество перестановок c меньшими первыми элементами (их (a[0]-1)*(n-1)!. Потом задача сводится к преведущей - сгенерировать k-ую перестановку среди оставшихся n-1 элементов.

    Если использовать какое-нибудь дерево отрезков, чтобы быстро искать j-ый пока не занятый элемент, то все решение будет за O(n log n). Если делать совсем просто - двумя циклами - то будет O(n^2). Гораздо быстрее вашего O(n!).

    Надо только аккуратно обработать случаи, когда (n-1)! слишком большое. Фактически, вам надо найти максимальный факториал, который меньше k. Пока не спуститесь до этого момента нужно сразу брать первый незанятый элемент и не считать факториал вообще.
    Ответ написан
    Комментировать
  • Как сделать дерево объектов из массива?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Не специалист по JS, но похоже там можно сделать проще чем стандартный обход графа в ширину/глубину.

    Заведите мап объектов, которые будете собирать. Ключи будудт айдишники, а значения - объекты. У объектов заполните uid, parentUID, пустой Map children и пустой список children_list. Так же запомните куда-то id, у которого null отец.

    Потом еще одним проходом по списку всех элементов заполните children_list у всех обхектов в Map из прошлого шага (кладите текущий id в список для parentUID).

    Потом еще одним проходом по всем элементам этого Map соберите дерево: обойдите список детей и в Map children кладите 'id' => объект из внешнего Map'а по данному ключу. После прохода можно children_list удалить.

    Если я правильно понимаю, как работает JS, то у вас будет не копироваться объект а его ссылка. В итоге в Map будут осодержаться вообще все поддеревья ссылыющееся друг на друга. Можно потом вырвать оттуда объект по ключу id корня и Map удалить.
    Ответ написан
    Комментировать
  • Есть ли алгоритм разложения матрицы?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Посмортите на метод Гаусса. Там получается диагональная матрица путем прибавления одной строки к другим и перестановки строк. Так вот - прибавление одной строки к другой с коэффициентом - это и есть домножение матрицы на трансвекцию.

    Единственная проблема - надо переставлять строчки местами. Тут вам поможет класический пазл о помене двух чисел без использования вспомогательных переменных:
    a = a + b;
    b = a - b;
    a = a - b;


    Эти три операции поменяют местами a и b. При чем они уже выглядят как трансвекции - только вторая операция не совсем вида a += b*k.

    Но можно чуть чуть поменять:
    a = a + b;
    b = b - a;
    a = a + b;


    Тут три трансвекции и строки меняются местами, только одна из них домножается на -1. Но это домножение метод гауса нисколько не меняет.

    Вот и ваш алгоритм.
    Ответ написан
    Комментировать
  • Как создать матрицу расстояний для нескольких точек?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Обход в ширину. Сначала поместите в очередь ваши начальные точки с расстоянием 0 и пометьте эти клетки в какой-то матрице как обработанные. Потом, пока очередь не пуста, доставайте из нее одну клетку, смотрите 4 соседние клетки и, если они пока не обработаны, кладите их в конец очереди с расстоянием +1 к текущей клетке. Также всегда помечайте клетки обработанными когда помещаете их в очередь.

    Работать это будет O(nm) - быстрее никак.
    Ответ написан
    Комментировать
  • Как найти сумму чисел на нечетных позициях после сортировки массива?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Никак. Есть методы получить число, которое будет стоять на заданной позиции (или числа на отрезке) в отсортированном массиве быстрее сортировки (алгоритм QuickSelect). Как-то быстрее сортировки найти все числа на нечетных позициях - нельзя.

    Edit: Если стандартная сортировка не работает и L большое, то стоит посмотреть в сторону radix sort. Если бы L было относительно небольшим - то лучший вариант был бы сортировка подсчетом.
    Ответ написан
  • Как реализовать битовую матрицу оптимально по памяти?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Максимально компактно - хранить одномерную матрицу в битах целочисленного массива - по 8 бит на байт.

    Для матрицы NxM бит (i,j) будет лежать в (i*N+j)/8 ячейке массива. Номер бита - надо взять остаток от деления на 8.

    Можно получить любой бит и можно что угодно делать с матрицей.
    Ответ написан
    Комментировать
  • Как сменить разряды двухбайтового числа (С++)?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вам нужно сделать побитовое И с маской, где стоят 0 в нужных вам разрядах (и 1 в остальных). Маску можно задавать прямо бинарной или шестнадцатеричной константой.
    Ответ написан
    Комментировать
  • Как найти все комбинации многоуровневого ассоциативного массива?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Рекурсивно. Функция должна получать уже набранный элемент и оставшиеся параметры. Она берет первый параметр и перебирает все его варианты, плюс пустой вариант (пропустить этот параметр). Добавляет это к элементу и рекурсивно запускается от оставшихся параметров с измененным элементом. Если параметров больеш нет - функция добавляет текущий ответ к результату. Правда этот алгоритм переберет еще и совсем пустой варинт []. Вам надо будет отдельно это проверить и не добавлять этот элемент в результат.
    Ответ написан
    1 комментарий