LeetCode[104/108/109] バイナリ ツリーの最大深さ、順序付き配列の二分探索ツリーへの変換、順序付きリンク リストの二分探索ツリーへの変換 C/C++——第 2 週 II

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]
1———————2

アイデア [再帰]:

この疑問は今でも再帰的な考えです。
この質問のタイトルは、順序付けされた配列を与え、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]。これは、表示されている高さバランスの取れた二分探索木を表します。

3

アイデア [再帰 + ダブル ポインタ]:

初めてこの種の質問を見たときは、何から始めて良いのか分からず、再帰的に書けそうな気もするが、中間ノードの見つけ方、つまり接続方法が分からなかった。次に、質問の説明でダブル ポインタ (高速ポインタと低速ポインタ) を使用できることがわかりました。高速ポインタは一度に 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);

おすすめ

転載: blog.csdn.net/Lailalalala/article/details/126128706