ホームページ  >  記事  >  バックエンド開発  >  PHP でバイナリ ツリーとバイナリ検索ツリーの最も近い共通の祖先を取得する方法

PHP でバイナリ ツリーとバイナリ検索ツリーの最も近い共通の祖先を取得する方法

醉折花枝作酒筹
醉折花枝作酒筹転載
2021-07-07 15:39:072365ブラウズ

二分探索ツリーが与えられた場合、ツリー内の指定された 2 つのノードに最も近い共通の祖先を見つけます。 Baidu 百科事典における最も近い共通の祖先の定義は次のとおりです。「ルート付きツリー T の 2 つのノード p と q について、最も近い共通の祖先はノード x として表されます。x は p と q の祖先であり、深さはノード x です。 x はできるだけ大きいです。"

PHP でバイナリ ツリーとバイナリ検索ツリーの最も近い共通の祖先を取得する方法

二分探索木の最も近い共通の祖先

二分探索ツリーを指定すると、このツリー内の指定された 2 つのノードの最も近い共通の祖先を見つけます。

百度百科事典における最も近い共通の祖先の定義は次のとおりです。「ルート付きツリー T の 2 つのノード p と q について、最も近い共通の祖先はノード x として表され、x は p の祖先になります。 q および x の深さはできるだけ大きくします (ノードはそれ自身の祖先になることもできます)。"

たとえば、次の二分探索ツリーがあるとします: root = [6,2,8,0 ,4,7, 9,null,null,3,5]

例 1:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6 
解释: 节点 2 和节点 8 的最近公共祖先是 6。

例 2:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

問題解決のアイデア

この質問では、二分探索木の最も近い共通の祖先を見つけるように求められます。二分探索木の特徴は、すべてのノードが左側のサブツリーにあることです。は現在のノードより小さく、右側のサブツリーのすべてのノードは現在のノードより小さいです。ノードはすべて現在のノードより大きく、各サブツリーは上記の特性を備えているため、この問題は簡単に解決できます。更新されたノード

2 つのノード値がルート ノードより小さい場合は、両方ともルート ノードにあることを意味します。 の左側のサブツリーで、左側のサブツリーに注目します。両方の場合、ノード値がルート ノードよりも大きい場合は、両方がルート ノードの右側のサブツリー上にあることを意味します。右側のサブツリーに注目します。ノード値がルート ノードより大きい場合、ノードの値がルート ノードよりも小さいということは、一方がルート ノードの左側のサブツリーにあり、もう一方がルート ノードの右側のサブツリーにあることを意味し、ルート ノードが最も近い共通の祖先ノードになります。

コード

/** 
* Definition for a binary tree node. 
* class TreeNode { 
    * public $val = null; 
    * public $left = null; 
    * public $right = null; 
    * function __construct($value) { 
        $this->val = $value; 
     } 
     * } 
*/
     class Solution {
    /** 
    * @param TreeNode $root 
    * @param TreeNode $p 
    * @param TreeNode $q 
    * @return TreeNode 
    */
    function lowestCommonAncestor($root, $p, $q) {
        //如果根节点和p,q的差相乘是正数,说明这两个差值要么都是正数要么都是负数,也就是说
        //他们肯定都位于根节点的同一侧,就继续往下找
        while (($root->val - $p->val) * ($root->val - $q->val) > 0)
            $root = $p->val < $root->val ? $root->left : $root->right;
        //如果相乘的结果是负数,说明p和q位于根节点的两侧,如果等于0,说明至少有一个就是根节点
        return $root;
    }}

バイナリ ツリーの最も近い共通の祖先

与えられたバイナリ ツリー、ツリー内の 2 つの指定されたノードの最も近い共通の祖先を見つけます。

百度百科事典における最も近い共通の祖先の定義は次のとおりです。「ルート付きツリー T の 2 つのノード p と q について、最も近い共通の祖先はノード x として表され、x は p の祖先になります。および q と ,null,7,4 の深さ]

例 1:

输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。

例 2:

输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。

解決策のアイデア

(再帰) O(n)

この質問を行うために再帰を使用する場合、質問に惑わされないでください。この関数には 3 つの関数があること: 2 つのノード pp と qq

が与えられた場合、pp と qq の両方が存在する場合は、共通の祖先を返します。1 つだけ存在する場合は、既存のものを返します。pp も qq も存在しない場合は、NULL を返します。この質問は、「指定されたノードが両方とも存在する場合、上記の関数を自然に使用して問題を解決できます。」というものです。

具体的なアイデア: (1) 現在のノードの rootroot が NULL に等しい場合、NULL が直接返されます ( 2) rootroot が pp または qq に等しい場合、このツリーは pp または qq を返さなければなりません (3) 次に、左と右のサブツリーを再帰します 再帰的であるため、関数を使用した後、左と右のサブツリーはleftleft と rightright で表される結果を計算しました (4) このとき、leftleft が Empty の場合、最終結果は rightright のみを参照する必要があり、rightright が空の場合、最終結果は leftleft (5) のみを参照する必要があります。 ) leftleft と rightright が両方とも空でない場合、pp と qq の 2 つのノードしか与えられていないため、どちらも空ではなく、両側に 1 つずつあることを示します。したがって、rootroot はそれらの最新の共通祖先になります (6) leftleft と rightright が両方とも空、空を返す (実際には前のケースに既に含まれています)

時間計算量は O(n): 毎回 各ノードは最大 1 回、または主定理を使用してトラバースできます。空間計算量は O( n): システム スタック領域が必要です

コード

/** 
* Definition for a binary tree node. 
* class TreeNode { 
* public $val = null; 
* public $left = null; 
* public $right = null; 
* function __construct($value) { 
    $this->val = $value; 
} 
 * } 
 */
 class Solution {
    /** 
    * @param TreeNode $root 
    * @param TreeNode $p 
    * @param TreeNode $q 
    * @return TreeNode 
    */
    function lowestCommonAncestor($root, $p, $q) {
        if ($root == null || $root == $p || $root == $q)
            return $root;
        $left = $this->lowestCommonAncestor($root->left, $p, $q);
        $right = $this->lowestCommonAncestor($root->right, $p, $q);
        
        //如果left为空,说明这两个节点在cur结点的右子树上,我们只需要返回右子树查找的结果即可
        if ($left == null)
            return $right;
        //同上
        if ($right == null)
            return $left;
        //如果left和right都不为空,说明这两个节点一个在cur的左子树上一个在cur的右子树上,
        //我们只需要返回cur结点即可。
        if ($left && $right) {
            return $root;
        }
        return null;
    }}
推奨学習:

php ビデオ チュートリアル

以上がPHP でバイナリ ツリーとバイナリ検索ツリーの最も近い共通の祖先を取得する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はhxd.lifeで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。