public static function getSequences(BinaryTreeNode $node)
 {
     $prefix = [$node->getData()];
     $left = $node->getLeft();
     $right = $node->getRight();
     if ($left === null && $right === null) {
         return [$prefix];
     }
     $leftSequences = $left !== null ? self::getSequences($left) : null;
     $rightSequences = $right !== null ? self::getSequences($right) : null;
     $sequences = [];
     if ($leftSequences === null) {
         foreach ($rightSequences as $rightSequence) {
             $sequences[] = array_merge($prefix, $rightSequence);
         }
         return $sequences;
     }
     if ($rightSequences === null) {
         foreach ($leftSequences as $leftSequence) {
             $sequences[] = array_merge($prefix, $leftSequence);
         }
         return $sequences;
     }
     // combine $leftSequences and $rightSequences in every possible way
     foreach ($leftSequences as $leftSequence) {
         foreach ($rightSequences as $rightSequence) {
             $mergedSequence = array_merge($leftSequence, $rightSequence);
             $orderings = self::getAllOrderings($mergedSequence);
             foreach ($orderings as $ordering) {
                 $sequences[] = array_merge($prefix, $ordering);
             }
         }
     }
     return $sequences;
 }
 public static function isBinarySearchTree(BinaryTreeNode $node, $min = null, $max = null)
 {
     $left = $node->getLeft();
     $right = $node->getRight();
     $nodeValue = $node->getData();
     if ($left !== null) {
         $leftValue = $left->getData();
         if ($nodeValue < $leftValue) {
             return false;
         }
         if ($min !== null && $min > $leftValue) {
             return false;
         }
         if (!self::isBinarySearchTree($left, $min, $nodeValue)) {
             return false;
         }
     }
     if ($right !== null) {
         $rightValue = $right->getData();
         if ($nodeValue > $rightValue) {
             return false;
         }
         if ($max !== null && $max < $rightValue) {
             return false;
         }
         if (!self::isBinarySearchTree($right, $nodeValue, $max)) {
             return false;
         }
     }
     return true;
 }
 public function testBinaryTreeNode()
 {
     $node1 = new BinaryTreeNode('Dizzy');
     $this->assertEquals('Dizzy', $node1->getData());
     $this->assertEquals('Dizzy', (string) $node1);
     $node1->setData('Miles');
     $this->assertEquals('Miles', $node1->getData());
     $this->assertEquals('Miles', (string) $node1);
     $this->assertNull($node1->getLeft());
     $this->assertNull($node1->getRight());
     $node2 = new BinaryTreeNode('Cannonball');
     $node3 = new BinaryTreeNode('Coltrane');
     $node1->setLeft($node2);
     $node1->setRight($node3);
     $this->assertSame($node2, $node1->getLeft());
     $this->assertSame($node3, $node1->getRight());
 }
 public static function countPathsWithSum(BinaryTreeNode $node, $targetSum, array $breadCrumb = [])
 {
     $newBreadCrumb = array_merge($breadCrumb, [$node->getData()]);
     $resultCount = self::getPathSumCount($newBreadCrumb, $targetSum);
     $left = $node->getLeft();
     if ($left !== null) {
         $resultCount += self::countPathsWithSum($left, $targetSum, $newBreadCrumb);
     }
     $right = $node->getRight();
     if ($right !== null) {
         $resultCount += self::countPathsWithSum($right, $targetSum, $newBreadCrumb);
     }
     return $resultCount;
 }
 public static function countPathsWithSum(BinaryTreeNode $node = null, $targetSum, $runningSum = 0, array &$pathCountMap = [])
 {
     if ($node === null) {
         return 0;
     }
     $runningSum += $node->getData();
     $sum = $runningSum - $targetSum;
     $totalPaths = array_key_exists($sum, $pathCountMap) ? $pathCountMap[$sum] : 0;
     if ($runningSum === $targetSum) {
         $totalPaths++;
     }
     $pathCountMap[$runningSum] = (array_key_exists($runningSum, $pathCountMap) ? $pathCountMap[$runningSum] : 0) + 1;
     $totalPaths += self::countPathsWithSum($node->getLeft(), $targetSum, $runningSum, $pathCountMap);
     $totalPaths += self::countPathsWithSum($node->getRight(), $targetSum, $runningSum, $pathCountMap);
     $pathCountMap[$runningSum] -= 1;
     return $totalPaths;
 }
 public static function getMaxDepthOrNegativeOneIfUnbalanced(BinaryTreeNode $node = null)
 {
     if ($node === null) {
         return 0;
     }
     $leftDepth = self::getMaxDepthOrNegativeOneIfUnbalanced($node->getLeft());
     if ($leftDepth == -1) {
         return -1;
     }
     $rightDepth = self::getMaxDepthOrNegativeOneIfUnbalanced($node->getRight());
     if ($rightDepth == -1) {
         return -1;
     }
     if (abs($leftDepth - $rightDepth) > 1) {
         return -1;
     }
     return max($leftDepth, $rightDepth) + 1;
 }
 protected static function findFirstCommonAncestorResult(BinaryTreeNode $node, BinaryTreeNode $p, BinaryTreeNode $q)
 {
     $isP = $node === $p;
     $isQ = $node === $q;
     $left = $node->getLeft();
     $right = $node->getRight();
     $leftIsP = false;
     $leftIsQ = false;
     $leftResult = null;
     if ($left !== null) {
         $leftResult = self::findFirstCommonAncestorResult($left, $p, $q);
         $leftReturnNode = $leftResult !== null ? $leftResult->getNode() : null;
         $leftIsP = $leftReturnNode === $p;
         $leftIsQ = $leftReturnNode === $q;
         if ($isP && $leftIsQ || $isQ && $leftIsP) {
             return new CommonAncestorResult($node, 2);
         }
     }
     $rightIsP = false;
     $rightIsQ = false;
     $rightResult = null;
     if ($right !== null) {
         $rightResult = self::findFirstCommonAncestorResult($right, $p, $q);
         $rightReturnNode = $rightResult !== null ? $rightResult->getNode() : null;
         $rightIsP = $rightReturnNode === $p;
         $rightIsQ = $rightReturnNode === $q;
         if ($isP && $rightIsQ || $isQ && $rightIsP) {
             return new CommonAncestorResult($node, 2);
         }
     }
     if ($leftIsP && $rightIsQ || $leftIsQ && $rightIsP) {
         return new CommonAncestorResult($node, 2);
     }
     if ($leftResult !== null) {
         return $leftResult;
     } elseif ($rightResult !== null) {
         return $rightResult;
     } elseif ($isP || $isQ) {
         $coverCount = ($isP ? 1 : 0) + ($isQ ? 1 : 0);
         return new CommonAncestorResult($node, $coverCount);
     }
     return null;
 }