У меня есть список всех подмножеств размера k из набора {1, 2, ..., n}, упорядоченного в лексикографическом порядке, например, все подмножества размера 2 из набора {1, 2, 3, 4} являются {1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4}. где индекс {1, 2} равен 0, {1, 3} равен 1 и т. д.Получение лексикографического индекса подмножества
Теперь мне нужно написать алгоритм, который получает подмножество (предположим, что подмножество упорядочено) и возвращает его индекс в списке.
Я написал следующий алгоритм:
int GetSubsetIndex(List<int> subset, int N)
{
int Skip = 0;
int Last = 0;
int Depth = 1;
int K = subset.Count;
while (Depth <= K)
{
for (int i = Last + 1; i < subset[Depth - 1]; i++)
{
Skip += BinomialCoefficient(N - i, K - Depth);
}
Last = subset[Depth - 1];
Depth++;
}
return Skip;
}
Этот алгоритм использует специальную структуру лексикографического порядка подмножеств, вот объяснение:
Допустим, у нас есть набор размером 6 (N = 6) и подмножество длины 3 (K = 3), то мы получим 6 подмножеств. теперь число подмножеств, начинающихся с 1, равно 5, выбор 2, число подмножеств, начинающихся с 2, равно 4, выбор 2 и т. д.
Если первое число в подмножестве X, мы можем skip (N-1 выбрать K-1) + (N-2 выбрать K-1) + ... + (NX выбрать K-1) подмножества. Если X было первым числом, второе число Y в подмножестве не менее X + 1. Теперь мы можем пропустить (N- [X + 1] выбрать K-2) + (N- [X + 2] выбрать K-2) + ... + (N-Y выбрать K-2) и т. Д.
В коде алгоритма Skip представляет количество подмножеств, которые мы пропустили, последний представляет последнее число, которое мы рассмотрели в подмножестве (инициализировано 0, когда набор начинается с 1), Глубина - это то, насколько глубоко мы находимся в подмножестве, и K - длина всех подмножеств.
Задача этого алгоритма, который работает с O(N)
время, если расчет биномиальный коэффициент O(1)
(если он был предварительно обработан) или O(N*k)
(если это не было), на практике некоторые подмножества могут быть вычислены очень быстро , Я пытаюсь понять, как получить этот индекс с короткой временной привязкой.
Вы можете выполнить любую предварительную обработку, если вы не используете больше, чем O(N chooke K)
памяти, то есть количество подмножеств.
Считаете ли вы использование бинарного поиска? –
Да, двоичный поиск дает худшую оценку, так как каждое сравнение принимает время O (K), а высота дерева - log2 (N выбирает K), если он хорошо сбалансирован. –
Это дубликат [этого вопроса] (http://stackoverflow.com/questions/5307222/how-to-calculate-the-index-lexicographic-order-when-the-combination-is-given?rq=1), который получил некоторые хорошо объясненные ответы. Не уверен, что вы будете делать лучше, чем O (n), но было бы интересно, если вы сможете это сделать –