Comments 13
Вы кажется очень лихо оценили сложность сортировки.
Теперь не могу вызвать std::swap, потому что prev укажет на слово next на следующем шаге цикла.
Просто нужно использовать words[write-1] вместо prev.
https://en.cppreference.com/w/cpp/algorithm/sort.html
Complexity
Given N as last - first:
1,2) O(N·log(N)) comparisons using operator<(until C++20)std::less{}(since C++20).
3,4) O(N·log(N)) applications of the comparator comp
Упс, ошибся, когда написал :)
Видимо, слова words короткие, поэтому решение со std::sort работает не хуже подсчета букв в массиве.
Для map вы неправильно посчитали асимптотику.
Там будет О(n * log (m)) где m количество букв, в данном случае 26. То есть асимптотика будет O(n)
https://en.cppreference.com/w/cpp/container/map/operator_at.html
Complexity
Logarithmic in the size of the container.
Спасибо. Верно ли я понял?
m - размер контейнера, сложность map::operator[] - log(m).
n - размер массива - вход алгоритма.
Считаем сложность
map::operator[]константойO(1), когдаmне зависит отn. Тогда сложность алгоритма -O(n * log(m))все равно чтоO(n). Например:латинский алфавит из 26 букв
map<char, ...>,m = 26любой символ
charот0до0xFF,m = sizeof(char) = 255
Сложность
map::operator[]-log(n), если быmзависел отn. Тогда сложность алгоритма -O(n * log(n))
зашел на литкод и посмотрел задачку, и подумал щас
а что если проходиться по вектору, входному, и каждое слово тоесть побуквено кидать в своё дерево(бинарное), которое при добавлении сортирует буквы, когда дошли до конца вектора, имеем отсортированные слова, ну а там сравниваем и скипаем повторы как я понял
Leetcode сообщает "твое решение работает за 1 мс - это быстрее 90% других". Это разовое измерение. Это значит, что твой алгоритм - лучший по сложности
, но в этот раз не повезло. Запусти еще раз, и тот же код способен отработать за 0 мс.
чатгпт?
words[w++] = std::move(words[r])уничтожит строку, когдаw == r, аstd::swapнет. Напишите в комментариях, почему так.
это не так
C++предлагает иstd::array, но не обнуляет массив. Элементыvector<int> stat(26)равны нулю, аarray<int, 26> stat- нет
что-то мне подсказывает, что есть способ инициализировать массив...
А если уж по задаче, то я думаю лучше посчитать хеш не зависящий от порядка и сравнить его перед тем как проверять
Я привел пример кода, в котором в векторе остаются пустые строки после words[i] = std::move(words[i]). Я проверил пример на Leetcode и другом компиляторе онлайн. Причина мне неясна, поэтому я попросил объяснить в комментариях. А Вы потрудились запустить пример и проверить или спорите без аргументов?=)


что-то мне подсказывает, что есть способ инициализировать массив...
Вы очень догадливы, способ есть =)
я думаю лучше посчитать хеш не зависящий от порядка и сравнить его перед тем как проверять
Так напишите код и проверьте. Такую функцию нужно придумать или найти. Круто блеснуть знаниями и показать "секретное" решение, но сперва напишите, тогда хвастайтесь =)
пустые строки после
words[i] = std::move(words[i])
это зависит от реализации, если вы говорите о std string. Просто формально не всегда это "уничтожит строку". Почему так - потому что кто-то решил оптимизировать строку и убрать лишнюю проверку
Вы очень догадливы, способ есть =)
так вот вы вместо того чтобы написать = {} выбрали использовать std vector
Так напишите код и проверьте.

is_anagram как-то сложновато. Выше же сами писали про хэш, который не зависит от порядка. Сам когда-то на том же LeetCode решал похожую задачу на анаграммы и там хватило даже вот такого:
static constexpr int BASE = 131;
static constexpr long long MOD = 1e9 + 7;
long long int compute_key(string_view word) {
array<int, 26> freq{};
for (char c : word) {
freq[c - 'a']++;
}
long long key = 0;
for (int count : freq) {
key = (key * BASE + count) % MOD;
}
return key;
}Хотя наверняка при тестировании на больших массивах данных будут коллизии.
Принципиально не пишу код, где возможны коллизии ради микрооптимизации
Во-первых, микрооптимизации или нет может сказать benchmark, разве вы его проводили? Я лично не умею заранее определять степень оптимальности глядя на код. Во-вторых, хэш функции, которые не учитывают порядок, предложили именно вы, только по факту сделали sum, у которого "ad" и "bc" дают один и тот же результат, догадываюсь, что когда вы это поняли на тестовых данных, просто добавили код который ещё разок бежит по строке и считает символы. Оптимальненько :)
Практически любая хэш сумма потенциально имеет коллизии, поэтому мне и непонятно зачем вы это предложили для того чтобы отказаться от сортировки, если заявляете что не пишите код с коллизиями ради микрооптиммзаций.
Нет, всё именно как и задумывалось
хэш функции, которые не учитывают порядок
"ad" и "bc" дают один и тот же результат, догадываюсь, что когда вы это поняли на тестовых данных, просто добавили код
именно это и делает сумма всех символов в строке. Именно этого я и добивался, убрал проверки на анаграмму для точно не подходящих строк
ещё разок бежит по строке и считает символы.
это оптимально, потому что тут выбор либо возможность коллизии (некорректный ответ), либо проверка
Я выбрал vector, но коротко упомянул, что массив в C++ реализует и array, но по умолчанию array не обнуляет элементы. Этим он похож на массив Си.
C++ разрешает инициализировать переменные с помощью = {}: так мы обнулим array или другие примитивные типы языка Си - int, double и прочие.
Статья - о легкой задаче, а не богатстве C++. Желающий найдет ответ "Почему так?" в документации по vector и array.
https://en.cppreference.com/w/cpp/container/vector.html
https://en.cppreference.com/w/cpp/container/array.html
Я пишу так, чтобы текст увлекал, а не отталкивал. Иной автор так боится погрешить против истины, что никак не поставит точку в предложении.
Программирование, математика - ужасно интересны, но часто пишут о них так, словно знания - для избранных, а прочие смертные - недостойны. Помните, не всякий гранит - научный, гранит и надгробием служит.
Спасибо за Ваши дополнения :)
Задачи по алгоритмам: избавляемся от анаграмм