セットのパーティションの生成
セットをパーティションと呼ばれる個別のサブセットに分割することは、一般的な数学演算です。この記事では、順序の無関係によって重複が発生しないように、セットを分割する効率的な方法を詳しく掘り下げます。
再帰的アプローチ
私たちのソリューションは再帰的戦略を利用しています。まずは最も単純なシナリオ、すなわち正確に 2 つの部分に分割することから始めます。各要素をビット (最初の部分は 0、2 番目の部分は 1) として表すことにより、最初の要素を最初の部分に一貫して配置することで重複した結果を回避します。
次に、再帰関数を詳しく調べます。より複雑なパーティションに対応します。この関数は元のセットに対して動作し、2 部構成のパーティションをすべて検索します。各パーティションの 2 番目の部分は再帰的に 2 つの部分に分割され、3 つの部分からなるパーティションが生成されます。このプロセスは、セット全体が分割されるまで続きます。
実装
以下は、分割アルゴリズムの C# 実装です。
using System; using System.Collections.Generic; using System.Linq; namespace PartitionTest { public static class Partitioning { public static IEnumerable<T[][]> GetAllPartitions<T>(T[] elements) { return GetAllPartitions(new T[][]{}, elements); } private static IEnumerable<T[][]> GetAllPartitions<T>( T[][] fixedParts, T[] suffixElements) { // A trivial partition consists of the fixed parts // followed by all suffix elements as one block yield return fixedParts.Concat(new[] { suffixElements }).ToArray(); // Get all two-group-partitions of the suffix elements // and sub-divide them recursively var suffixPartitions = GetTuplePartitions(suffixElements); foreach (Tuple<T[], T[]> suffixPartition in suffixPartitions) { var subPartitions = GetAllPartitions( fixedParts.Concat(new[] { suffixPartition.Item1 }).ToArray(), suffixPartition.Item2); foreach (var subPartition in subPartitions) { yield return subPartition; } } } private static IEnumerable<Tuple<T[], T[]>> GetTuplePartitions<T>( T[] elements) { // No result if less than 2 elements if (elements.Length < 2) yield break; // Generate all 2-part partitions for (int pattern = 1; pattern < 1 << (elements.Length - 1); pattern++) { // Create the two result sets and // assign the first element to the first set List<T>[] resultSets = { new List<T> { elements[0] }, new List<T>() }; // Distribute the remaining elements for (int index = 1; index < elements.Length; index++) { resultSets[(pattern >> (index - 1)) & 1].Add(elements[index]); } yield return Tuple.Create( resultSets[0].ToArray(), resultSets[1].ToArray()); } } } }
分割の呼び出し.GetAllPartitions(new[] { 1, 2, 3, 4 }) は、次のパーティション:
{ {1, 2, 3, 4} }, { {1, 3, 4}, {2} }, { {1, 2, 4}, {3} }, { {1, 4}, {2, 3} }, { {1, 4}, {2}, {3} }, { {1, 2, 3}, {4} }, { {1, 3}, {2, 4} }, { {1, 3}, {2}, {4} }, { {1, 2}, {3, 4} }, { {1, 2}, {3}, {4} }, { {1}, {2, 3, 4} }, { {1}, {2, 4}, {3} }, { {1}, {2, 3}, {4} }, { {1}, {2}, {3, 4} }, { {1}, {2}, {3}, {4} }.
以上がC# で再帰的アプローチを使用してセットのすべてのパーティションを効率的に生成するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。