符号ランダム記録アルゴリズム合宿22日目|235.二分探索木の最近接共通祖先 701.二分探索木への挿入操作 450.二分探索木のノードの削除

目次

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

1. 再帰的実装

2. 反復法の実装

 701. 二分探索木への挿入操作(再帰実装)

450. 二分探索木のノードを削除する(再帰的実装)


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

この質問は、二分探索木の特性を利用できるため、二分木の最も近い共通祖先と比較して簡単です。

トピックリンク/記事説明: code caprice

解決策のアイデア:

1. 再帰的実装

反復法と再帰法の原理は同じで、実はこの反復法の本質は再帰法だと思いますが、手順が違います。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        while(root != null){
            if(root.val > p.val && root.val > q.val){
                TreeNode left = lowestCommonAncestor(root.left,p,q);
                if(left != null) return left;
            }else if(root.val < p.val && root.val < q.val){
                TreeNode right = lowestCommonAncestor(root.right,p,q);
                if(right != null) return right;
            }else{
                return root;
            }
        }
        return null;
    }
}

2. 反復法の実装

反復法と再帰法の原理は同じで、実はこの反復法の本質は再帰法だと思いますが、手順が違います。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        while(root != null){
            if(root.val > p.val && root.val > q.val){
                TreeNode left = lowestCommonAncestor(root.left,p,q);
                if(left != null) return left;
            }else if(root.val < p.val && root.val < q.val){
                TreeNode right = lowestCommonAncestor(root.right,p,q);
                if(right != null) return right;
            }else{
                return root;
            }
        }
        return null;
    }
}

 701. 二分探索木への挿入操作(再帰実装)

この問題は想像よりも簡単です。自分で解き方を考えてからビデオの解説を見ると、この問題が比較的簡単である理由がわかります。

トピックリンク/記事説明: code caprice

解決策のアイデア:

Ka Ge のビデオ解説をもっと聞いてください! バイナリ ツリーでの挿入操作はバイナリ ツリーを構築することです。リーフ ノードに挿入したいノードを見つけることができなければなりません。その後、特性に従って現在のノードの val 値と指定された val を比較できます。二分探索木の左側のサブツリーにあるかどうかを直接判断し、右側のサブツリーが挿入されます。最後に、ルート ノードに直接戻るだけです。Ka Geさんの説明を聞く前はただの混乱でしたが、最初の感覚は非常に複雑で、挿入方法などもさまざまでした!Ka Ge のビデオ説明を聞いた後でも、考え方は明確です。心を開くには、もっと聞いて、もっと見て、もっとスワイプする必要があります。非科学クラスのトランスコーディングは確かに少し面倒で、これまで訓練されていなかった考え方を根本から覆します。来て!

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    
    public TreeNode insertIntoBST(TreeNode root, int val) {
        //第二步:确定终止条件
        if(root == null) return new TreeNode(val);;

        //第三步:确定单层处理逻辑
        if(root.val > val){
            root.left = insertIntoBST(root.left,val); //直接根据二叉搜索树的特性比较当前节点的val值和给定的val,直接判断在其左子树还是右子树进行插入操作
        }else if(root.val < val){
            root.right = insertIntoBST(root.right,val); //直接根据二叉搜索树的特性比较当前节点的val值和给定的val,直接判断在其左子树还是右子树进行插入操作
        }

        return root;
    }

    
}

作者:vansven-h
链接:https://leetcode.cn/problems/insert-into-a-binary-search-tree/solution/701er-cha-sou-suo-shu-zhong-de-cha-ru-ca-fj39/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

450. 二分探索木のノードを削除する(再帰的実装)

この問題は挿入操作に比べて難しく、ツリーの構造を変更する必要があります。

トピックリンク/記事説明: code caprice

解決策のアイデア:

主な理由は、ノードの削除には 5 つの異なる状況があり、状況に応じて 1 つずつ対処する必要があるためです。具体的な 5 つの状況については、以下のコメント付きコードを参照してください。私が言いたいのは、一度スワイプしたら、もっと見て、Kage のビデオを聞いて、もっとスワイプする必要があるということです。方法論をマスターすることによってのみ、独自のホイールを構築するための資本を得ることができます。これらは基本的なアルゴリズムであり、実際にはそうする必要はありませんどうやって話せばいいのか分からない、高度な知識!

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        //第二步:确定终止条件,当找到五种不同情况的节点需要删除时,此时就是遍历到的节点就是终止条件,需要及时对找到的节点进行处理才行
        if(root == null) return null; //第一种情况:没找到要删除的节点,直接返回null值即可
        else if(root.val == key){     //以下四种情况都是在找到要删除节点的情况下进行讨论的
            if(root.left == null && root.right == null) return null; //第二种情况:删除的时叶子节点
            else if(root.left != null && root.right == null) return root.left; //第三种情况:删除左不为空,右为空的节点
            else if(root.left == null && root.right != null) return root.right;//第四种情况:删除左为空,右不为空的节点
            else{
                TreeNode current = root.right;  //第五种情况:删除左不为空,右不为空的节点,根据二叉搜索树的特性,需要一直搜索右子树的左节点,一直其叶节点进行插入
                while( current.left != null){
                    current = current.left;
                }
                current.left = root.left;
                return root.right;
            }
        }

        //第三步:确定单层处理逻辑,根据二叉树的搜索特性,直接比较当前遍历节点的val值和key值,直接判断在其左子树还是右子树进行删除节点操作
        if(root.val > key) root.left = deleteNode(root.left,key);
        else if(root.val < key) root.right = deleteNode(root.right,key);

        return root;
    }
}

おすすめ

転載: blog.csdn.net/tore007/article/details/130628721