104. 二分木の最大深さ
タイトル説明[簡単]:
二分木が与えられた場合、その最大の深さを見つけます。
バイナリ ツリーの深さは、ルート ノードから最も遠いリーフ ノードまでの最長パス上のノードの数です。
例 1:
入力: [3,9,20,null,null,15,7]
出力: 3
アイデア [再帰]:
この質問の考え方は昨日の質問と同じで、どちらも再帰で行うことができます。
まず、空の場合をリストする必要があり、この時点では 0 を出力します。
ノードがある場合は、左のサブツリーの深さの値と右のサブツリーの深さの値を比較して、どちらが正しいかを確認する必要があります。最大。ここで注意すべき点が 1 つあります。それは、最上位のルート ノードのルートをカウントする必要があるということです。したがって、 を返すときは+1が必要です。
左の部分木と右の部分木の深さを見るということは、左の部分木の部分木の深さを見ることになる、これが再帰の考え方です。
再帰条件の終了: ツリーは一番下までたどられ、サブツリーは空になります。
C++ コード:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root == NULL)
return 0;
return max(maxDepth(root->left),maxDepth(root->right)) + 1;
}
};
108. ソートされた配列を二分探索木に変換する
タイトル説明[簡単]:
要素が昇順にソートされている整数配列 nums を指定して、高さのバランスがとれた二分探索ツリーに変換してください。
高さバランス二分木とは、「各ノードの左右の部分木の高さの差の絶対値が1を超えない」を満たす二分木である。
例 1:
入力: nums = [-10,-3,0,5,9]
出力: [0,-3,9,-10,null,5]/[0,-10,5,null,-3 ,null,9]
———————
アイデア [再帰]:
この疑問は今でも再帰的な考えです。
この質問のタイトルは、順序付けされた配列を与え、BST を作成することです。誰もが知っているように、BST の順序トラバーサルは配列の昇順であるため、この質問は次のようになります。
BST の順序シーケンスを通じて、この BST ツリーの層順序トラバーサル シーケンスを推測します。
昇順の任意の要素をルート ノードとして取得し、要素の左側の要素を昇順に並べて左のサブツリーを構築し、要素の右側の要素を昇順に並べて右のサブツリーを構築できます。 。また、高さのバランスがとれたツリーであるため、昇順シーケンスの中央の要素をルート ノードとして選択します。
C++ コード:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
return sortedArray(nums , 0 , nums.size()-1);
}
TreeNode* sortedArray(vector<int>& nums , int l , int r){
if(r<l)//如果数组为空
return nullptr;//直接返回空结点
int mid = l + (r-l) / 2;// 以升序数组的中间元素作为根节点 root
TreeNode* root = new TreeNode(nums[mid]);//把中间节点作为根节点
root->left = sortedArray(nums, l, mid - 1);// 通过递归的方式来构建 root 的左子树
root->right = sortedArray(nums, mid + 1, r);//通过递归的方式来构建 root 的右子树
return root;
}
};
109. ソートされたリンクリストを二分探索木に変換する
タイトル説明[中]:
要素が昇順にソートされている単一リンクリストのヘッドノードが与えられた場合、それを高さのバランスがとれた二分探索木に変換します。
このうち、高さバランスのとれた二分木とは、二分木の各ノードの左右の部分木の高さの差が 1 を超えないことを意味します。
例 1:
入力: head = [-10,-3,0,5,9]
出力: [0,-3,9,-10,null,5]
説明: 考えられる答えの 1 つは [0,-3, 9] です。 , -10, null, 5]。これは、表示されている高さバランスの取れた二分探索木を表します。
アイデア [再帰 + ダブル ポインタ]:
初めてこの種の質問を見たときは、何から始めて良いのか分からず、再帰的に書けそうな気もするが、中間ノードの見つけ方、つまり接続方法が分からなかった。次に、質問の説明でダブル ポインタ (高速ポインタと低速ポインタ) を使用できることがわかりました。高速ポインタは一度に 2 ステップずつ移動し、低速ポインタは一度に 1 ステップずつ移動します。
次に、リンク リストの中間ノード メソッド:
高速ポインタと低速ポインタは、最初にヘッド ノードを指し、それぞれ一度に 2 ステップと 1 ステップを実行します。高速ポインタが末尾ノードに到達すると、低速ポインタはそのままノードに移動します。リンクリストの真ん中。この時点で、リンクされた 2 つのリストに分割され、分離されます。
リンクリストの切断を実現する方法:
スローポインタの前のノードを保存するためのヌルポインタを作成し、切断操作を実現します。現在のリストではなく前のリストを保存する理由は、単一リンク リストのノードには先行ポインタが存在しないためです。
C++ コード:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* sortedListToBST(ListNode* head) {
if(head==nullptr)
return nullptr;
if(head->next == nullptr) //如果只有一个节点
return new TreeNode(head->val); //直接创建,然后返回
ListNode* mid = getMid(head);//调用中间值方法
//构造二叉树
TreeNode* root = new TreeNode(mid->val);//此时根节点就是中间节点
root->left = sortedListToBST(head);//递归构造左子树,由于链表在中间节点前断开,所以直接传入头结点
root->right = sortedListToBST(mid->next);//递归构造右子树,此时传入中间节点的下一个节点
return root;
}
ListNode* getMid(ListNode* head){
//获取链表中间节点的方法,在获得中间值同时还要把链表在中间值前断开(方便递归操作)
ListNode* node = nullptr;//定义一个空指针
ListNode* fast = head;//利用双指针来找中间节点,此时定义两个指针,快指针和慢指针
ListNode* slow = head;
while(fast && fast->next){
fast = fast->next->next;//快指针一次移动两步
node = slow;//更新node指针
slow = slow->next;//慢指针一次移动一步
}
if(node!=nullptr)//移动结束后,node非空,就在此断开链表
node->next = nullptr;
return slow;
}
};
時間計算量: O(nlogn);