Без особой причины я решил поискать алгоритм, который выдает все возможные варианты выбора k целых чисел от 1 до n, где порядок между k целыми числами не имеет значения (n выбирает k штук).
По той же самой причине, которая вовсе не является причиной, я также реализовал ее в C #. Мой вопрос:
Видите ли вы ошибку в моем алгоритме или коде? И, что более важно, Вы можете предложить лучший алгоритм?
Пожалуйста, обратите больше внимания на алгоритм, чем на сам код. Это не самый красивый код, который я когда-либо писал, хотя скажите, если увидите ошибку.
РЕДАКТИРОВАТЬ: Alogirthm объяснил -
- Мы держим k индексов.
- Это создает k вложенных для циклов, где индексом цикла i являются индексы [i].
- Имитирует k для циклов , где индексы [i + 1] принадлежат циклу, вложенному в цикл индексов [i].
- индексы [i] идут от индексов [i - 1] + 1 к n - k + i + 1.
КОД:
public class AllPossibleCombination
{
int n, k;
int[] indices;
List<int[]> combinations = null;
public AllPossibleCombination(int n_, int k_)
{
if (n_ <= 0)
{
throw new ArgumentException("n_ must be in N+");
}
if (k_ <= 0)
{
throw new ArgumentException("k_ must be in N+");
}
if (k_ > n_)
{
throw new ArgumentException("k_ can be at most n_");
}
n = n_;
k = k_;
indices = new int[k];
indices[0] = 1;
}
/// <summary>
/// Returns all possible k combination of 0..n-1
/// </summary>
/// <returns></returns>
public List<int[]> GetCombinations()
{
if (combinations == null)
{
combinations = new List<int[]>();
Iterate(0);
}
return combinations;
}
private void Iterate(int ii)
{
//
// Initialize
//
if (ii > 0)
{
indices[ii] = indices[ii - 1] + 1;
}
for (; indices[ii] <= (n - k + ii + 1); indices[ii]++)
{
if (ii < k - 1)
{
Iterate(ii + 1);
}
else
{
int[] combination = new int[k];
indices.CopyTo(combination, 0);
combinations.Add(combination);
}
}
}
}
Я прошу прощения за длинный вопрос, возможно, он подходит для поста в блоге, но я хочу узнать мнение сообщества здесь.
Спасибо,
Асаф