特に理由はありませんが、1...n の間の k 個の整数のすべての可能な選択肢を生成するアルゴリズムを探すことにしました。ここで、k 個の整数の順序は重要ではありません (n は k のものを選択します)。
まったく同じ理由で、まったく理由はありませんが、C# でも実装しました。私の質問は:
私のアルゴリズムやコードに誤りはありますか? さらに重要なのは、より良いアルゴリズムを提案できますか?
コード自体よりもアルゴリズムに注意を払ってください。これは私がこれまでに書いた中で最も美しいコードではありませんが、エラーが発生した場合は教えてください。
編集:アルゴリズムの説明-
- k 個のインデックスを保持します。
- これにより、 forループのネストされた k が作成されます。ここで、ループ i のインデックスは index[i] です。
- これは、インデックス[i+1] がインデックス[i] のループ内にネストされたループに属するループのkをシミュレートします。
- インデックス[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);
}
}
}
}
長い質問で申し訳ありません。ブログ投稿に適しているかもしれませんが、ここでコミュニティの意見を求めています。
ありがとう、
アサフ