Хорошая хеш-функция для перестановок?

Я думаю, что не согласился бы с @bb и @JaredPar, и я склоняюсь к противоположной стороне забора. После лет попытки поддерживать другой код C++ народов, я часто нахожу проблемы, скрывающиеся в неочевидных побочных эффектах ссылочных аргументов. С C# это очевидно, так как необходимо снабдить префиксом типы споров с 'касательно'/'out', но ссылки потенциально сбивают с толку в C++. Так, мне нравятся указатели, потому что действительно ясно, что что-то возвращается. Если Вам не нравятся точки, C++ не для Вас.

12
задан martinus 29 December 2009 в 21:36
поделиться

6 ответов

Один потенциальный кандидат может быть это. Зафиксируем нечетное целое число R. Для каждого элемента e, который вы хотите хэшировать, вычислите коэффициент (R + 2 * e). Затем вычислите произведение всех этих факторов. Наконец, разделите произведение на 2, чтобы получить хэш.

Множитель 2 в (R + 2e) гарантирует, что все множители нечетные, что позволяет избежать что продукт когда-либо станет 0. Деление на 2 в конце происходит потому, что произведение всегда будет нечетным, поэтому при делении просто удаляется постоянный бит.

Например, я выбираю R = 1779033703. Это произвольный выбор, некоторые эксперименты должны показать, является ли данное R хорошим или плохим. Предположим, ваши значения - [1, 10, 3, 18]. Результатом (вычисленным с использованием 32-битных целых чисел) является

(R + 2) * (R + 20) * (R + 6) * (R + 36) = 3376724311

Следовательно, хэш будет

3376724311/2 = 1688362155.

6
ответ дан 2 December 2019 в 21:03
поделиться

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

Это полезно только в том случае, если вы получаете множество нежелательных коллизий потому что хеш, который вы сейчас делаете, слишком плох. Если столкновения почти не возникают, значит, метод, который вы используете, подходит

0
ответ дан 2 December 2019 в 21:03
поделиться

I would suggest this: 1. Check if the lengths of permutations are the same (if not - they are not equal)

  1. Sort only 1 array. Instead of sorting another array iterate through the elements of the 1st array and search for the presence of each of them in the 2nd array (compare only while the elements in the 2nd array are smaller - do not iterate through the whole array).

note: if you can have the same numbers in your permutaions (e.g. [1,2,2,10]) then you will need to remove elements from the 2nd array when it matches a member from the 1st one.

pseudo-code:

if length(arr1) <> length(arr2) return false;
sort(arr2);
for i=1 to length(arr1) {
elem=arr1[i];
j=1;
while (j<=length(arr2) and elem<arr2[j]) j=j+1;
if elem <> arr2[j] return false;
}
return true;

the idea is that instead of sorting another array we can just try to match all of its elements in the sorted array.

0
ответ дан 2 December 2019 в 21:03
поделиться

Мне нравится использовать хэш-код строки по умолчанию (Java, C # не уверен в других языках), он генерирует довольно уникальные хэш-коды. поэтому, если вы сначала отсортируете массив, а затем сгенерируете уникальную строку с использованием некоторого разделителя.

, чтобы вы могли сделать следующее (Java):

    int[] arr = selectRandomNumbers();
    Arrays.sort(arr);
    int hash = (arr[0] + "," + arr[1] + "," + arr[2] + "," + arr[3]).hashCode();

если производительность является проблемой, вы можете изменить предлагаемую неэффективную конкатенацию строк, чтобы использовать StringBuilder или String.format

   String.format("{0},{1},{2},{3}", arr[0],arr[1],arr[2],arr[3]);

Хеш-код строки, конечно, не гарантирует, что две разные строки имеют разные хеш-коды, но с учетом этого предлагаемого форматирования коллизии должны быть крайне редкими

0
ответ дан 2 December 2019 в 21:03
поделиться

Вы можете хранить локальные копии требуемых значений внешних объектов. Затем процедура доступа сравнивает локальную копию с внешним значением и выполняет пересчет только при изменении.

Доступ к свойствам внешних объектов также может вызвать возможную переоценку этих свойств, поэтому система должна поддерживать себя в актуальном состоянии автоматически, но пересчитывать только тогда, когда это необходимо. Я не знаю, нужно ли вам предпринимать шаги, чтобы избежать циклических зависимостей.

Это увеличивает пространство, необходимое для каждого объекта, но удаляет шаблон наблюдателя. Он также откладывает все вычисления до тех пор, пока они не потребуются, вместо того, чтобы выполнять вычисление каждый раз, когда изменяется параметр источника. Надеюсь, это актуально для вашей системы.

0
ответ дан 2 December 2019 в 21:03
поделиться

Суммирование элементов - это уже одна из самых простых вещей, которые вы можете сделать. Но я не думаю, что это особенно хорошая хеш-функция в отношении псевдослучайности.

Если вы отсортируете свои массивы перед их сохранением или вычислением хешей, подойдет любая хорошая хеш-функция.

скорость: Вы измерили узкое место? Если ваша хеш-функция дает вам много коллизий, и вам приходится тратить большую часть времени на побитовое сравнение массивов, хеш-функция, очевидно, не подходит для того, что она должна делать. Решением может стать сортировка и лучший хэш.

5
ответ дан 2 December 2019 в 21:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: