二分木
バイナリ ツリーは一般的なツリー状のデータ構造であり、ノードで構成され、各ノードには最大 2 つの子ノードがあります。
- 左側の子ノード
- 右の子ノード
これら 2 つの子ノードは空にすることも、他のノードに接続することもできます。バイナリ ツリーには次の特徴があります。
- 各ノードには最大 2 つの子ノードがあります。
- 左側の子ノードは親ノードの左側にあり、右側の子ノードは親ノードの右側にあります。
- 子ノードは空であってもかまいません。
簡単なバイナリ ツリーの例を次に示します。
1
/ \
2 3
/ \ / \
4 5 6 7
この例では、数字はノード値を表し、矢印は子ノード間の接続を表します。
ルート ノードは 1、その左の子は 2、右の子は 3 です。ノード 2 の左側の子ノードは 4、右側の子ノードは 5 です。ノード 3 の左側の子ノードは 6、右側の子ノードは 7 です。
これはバイナリ ツリーの例であり、各ノードには最大 2 つの子ノードがあり、バイナリ ツリーの定義に準拠しています。
詳細については、WeChat で「 前端爱好者
」を検索し、 「私」をクリックしてご覧ください。
フロントエンドは、たとえば、任意の 2 つのノードの最小祖先などのトラバーサル問題向けに設計されています。
バイナリ ツリーはどのような問題を解決するために使用されますか?
バイナリ ツリーはノードで構成されるデータ構造で、各ノードには左の子と右の子という最大 2 つの子があります。このデータ構造は、次のようなさまざまな問題を解決するために一般的に使用されますが、これらに限定されません。
データの整理と検索:
BST (Binary Search Tree) は、高速な検索、挿入、削除操作を可能にする一般的なバイナリ ツリーです。ノードの値を比較することで、データ項目を効率的に見つけることができ、データベースのインデックス作成や検索エンジンなどの分野で役立ちます。
例: 多くの単語が含まれる二分探索ツリーで特定の単語を検索すると、その単語をすばやく見つけて関連情報を提供できます。
並べ替え:
バイナリ ツリーは並べ替えアルゴリズムで使用できます。たとえば、順序付けされたデータは、二分探索ツリーを構築し、順序どおりの走査を実行することによって取得できます。
例: 一連の数値をソートし、それらを二分探索ツリーに構築し、次に順序トラバーサルを実行して、順序付けられた一連の数値を取得します。
式と計算:
式ツリーは、数式を表すために使用されるバイナリ ツリーです。式の評価と操作に役立ちます。
たとえば、「(3 + 4) * 5」などの数式を対応する二分木構造に表現して、演算と評価を容易にします。
グラフィック処理:
コンピュータ グラフィックスでは、バイナリ ツリー構造を使用して、シーン内のオブジェクトの構成などのシーン グラフまたは階層構造を表現できます。
例: コンピューター ゲームのシーンを表すにはバイナリ ツリーを使用します。各ノードはオブジェクトまたはシーン要素を表し、ツリー構造はそれらの間の階層関係を表すために使用されます。
これらはバイナリ ツリーの応用例のほんの一部であり、さまざまな分野で幅広い応用例があります。
例: 二分木の最新の共通祖先
バイナリ ツリーが与えられた場合、ツリー内の指定された 2 つのノードに最も近い共通の祖先を見つけます。
leetcode アドレス: https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/
最も近い共通の祖先の定義は次のとおりです。「ルート付きツリー T の 2 つのノード p と q について、最も近い共通の祖先はノード x として表されます。つまり、x は p と q の祖先であり、x の深さは次のようになります。可能な限り大きくしてください (1 つのノードがそれ自体の祖先である場合もあります)。
例 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 。因为根据定义最近公共祖先节点可以为节点本身。
例 3:
输入:root = [1,2], p = 1, q = 2
输出:1
ヒント:
树中节点数目在范围 [2, 105] 内。
-109 <= Node.val <= 109
所有 Node.val 互不相同 。
p != q
p 和 q 均存在于给定的二叉树中。
考え方:ソート・配置方法と現在のツリーとノードの関係(ソート時)
- 左側にあります
- 2 つのテストで判明
再帰:
返回当前子树中,p和q 的最近祖先,没有,返回null
1. 当前遍历到p或者 q.不无要往下遍历,返回当前p q
2. 遍历到null,没有p q,返回nul
3. 遍历子树,左子树 右子树 都有结果,返回root
4. 只有其中一个子树有结果 p / q 只在这个子树下返回 null,null
結果:
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {TreeNode} p
* @param {TreeNode} q
* @return {TreeNode}
*/
var lowestCommonAncestor = function(root, p, q) {
if(root == null){
return null
}
// 遇到p,遇到q,直接返回当前的节点
if(root ==p || root == q){
return root
}
// 递归操作
const left = lowestCommonAncestor(root.left, p, q)
const right = lowestCommonAncestor(root.right, p, q)
// 如果左子树和右子树都有节点,则返回root
if(left && right) {
return root
}
// 如果左节点没有,则返回右侧子树
if(!left){
return right
}
// 如果右节点没有,则返回左侧子树
if(!right){
return left
}
};
例 2: 二分探索木の最近の共通祖先
leetcode アドレス: https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/description/
二分探索ツリーを指定して、ツリー内の指定された 2 つのノードに最も近い共通の祖先を見つけます。
最新の共通祖先の定義は次のとおりです。「ルート付きツリー T の 2 つのノード p と q について、最新の共通祖先はノード x として表されます。x は p と q の祖先であり、x の深さは次のとおりです。可能な限り大きいものです (1 つのノード自体の祖先である可能性もあります)。」
たとえば、次の二分探索ツリーがあるとします: 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, 因为根据定义最近公共祖先节点可以为节点本身。
例証します:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉搜索树中。
答え
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {TreeNode} p
* @param {TreeNode} q
* @return {TreeNode}
*/
var lowestCommonAncestor = function(root, p, q) {
if(root == null){
return null
}
// 遇到p,遇到q,直接返回当前的节点
if(root ==p || root == q){
return root
}
// 递归操作
const left = lowestCommonAncestor(root.left, p, q)
const right = lowestCommonAncestor(root.right, p, q)
// 如果左子树和右子树都有节点,则返回root
if(left && right) {
return root
}
// 如果左节点没有,则返回右侧子树
if(!left){
return right
}
// 如果右节点没有,则返回左侧子树
if(!right){
return left
}
};