BSTのプロパティを維持しながら2つの二分探索木をマージする方法は?
ツリーから各要素を取得して他の要素に挿入することにした場合、このメソッドの複雑さはO(n1 * log(n2))
になります。ここで、n1
はツリーのノードの数(たとえばT1
)です。分割され、n2
は他のツリーのノードの数です(たとえばT2
)。この操作の後、1つのBSTのみにn1 + n2
ノードがあります。
私の質問は、O(n1 * log(n2))よりも優れた方法はありますか?
もう少し詳細なNaaffの答え:
O(n1 + n2)の3つのステップは、O(n1 + n2)になります。
同じ桁のn1とn2の場合、O(n1 * log(n2))よりも優れています。
[1]ソートされたリストからバランスの取れたBSTを作成するためのアルゴリズム(Python):
def create_balanced_search_tree(iterator, n):
if n == 0:
return None
n_left = n//2
n_right = n - 1 - n_left
left = create_balanced_search_tree(iterator, n_left)
node = iterator.next()
right = create_balanced_search_tree(iterator, n_right)
return {'left': left, 'node': node, 'right': right}
IIRC、つまりO(n1 + n2)。
両方のツリーをソートされたリストにフラット化し、リストをマージしてから新しいツリーを作成するのはどうですか?
ジョナサン、
ソート後、長さn1 + n2のリストがあります。それから二分木を構築するには、log(n1 + n2)の時間がかかります。これはマージソートと同じですが、各再帰ステップで、マージソートアルゴリズムのようにO(n1 + n2)項がない点が異なります。したがって、時間計算量はlog(n1 + n2)です。
ここで、問題全体の複雑さはO(n1 + n2)です。
また、2つのリストが同等のサイズである場合、このアプローチは適切だと思います。サイズが比較できない場合は、小さなツリーのすべてのノードを大きなツリーに挿入するのが最善です。これにはO(n1 * log(n2))時間がかかります。たとえば、サイズが10のツリーとサイズが1024のツリーが2つある場合、ここではn1 + n2 = 1034ですが、n1log(n2)= 10 * 10 = 100です。したがって、アプローチは2つのツリーのサイズに依存する必要があります。
O(n1 * log(n2))は、ソートされていないリストを2つマージしてBSTにした場合でも、平均的なシナリオです。リストがソートされたリストまたはBSTであるという事実を利用していません。
私によると、1つのBSTにn1個の要素があり、他のBSTにn2個の要素があると仮定しましょう。次に、1つのBSTをO(n1)のソート済み配列リストL1に変換します。
マージされたBST(BST、配列)
if(Array.size == 0)return BST if(Array.size == 1)要素をBSTに挿入します。 BSTを返します。
左側の要素<BST.rootnodeおよび右側の要素> = BST.rootnodeがIndexと言う配列内のインデックスを見つけます。 if(BST.rootNode.leftNode == null)// i.e左ノードなし{インデックスから0までのすべての配列をBSTの左側に挿入し、} else {マージされたBST(BST.leftNode、Array {0 to Index})}
if(BST.rootNode.rightNode == null)// ie右ノードがありません{IndexからArray.sizeまでのすべての配列をBSTの右側に挿入します} else {マージされたBST(BST.rightNode、Array {Index to Array.size} )}
bSTを返します。
このアルゴリズムは、サブ問題を処理するために配列とBSTを分割するたびに、O(n1 * log(n2))よりも<<時間がかかります。