程式碼隨想錄演算法 - 二叉樹

酱油黑龙發表於2024-09-10

題目1 226. 翻轉二叉樹

給你一棵二叉樹的根節點 root ,翻轉這棵二叉樹,並返回其根節點。

示例 1:

img

輸入:root = [4,2,7,1,3,6,9]
輸出:[4,7,2,9,6,3,1]

示例 2:

img

輸入:root = [2,1,3]
輸出:[2,3,1]

示例 3:

輸入:root = []
輸出:[]

提示:

  • 樹中節點數目範圍在 [0, 100]
  • -100 <= Node.val <= 100

思路

這道題可以用先序,中序,後序或者層序遍歷去做,思路都是類似的。

遞迴呼叫

注意遞迴結束條件是root為nullptr,在每個非空結點上進行左右孩子指標的交換就行了。

程式碼

/**
 * 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* invertTree(TreeNode* root) {
        if(root == nullptr) return root;
        TreeNode* tmp = root->left;
        root->left = root->right;
        root->right = tmp;
        invertTree(root->left);
        invertTree(root->right);
        return root;
    }
};

迭代遍歷翻轉

使用一個輔助的棧或者佇列來儲存子結點就可以做了。

程式碼

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        stack<TreeNode*> nodeStack;
        nodeStack.push(root);
        while(!nodeStack.empty())
        {
            TreeNode* curNode = nodeStack.top();
            nodeStack.pop();
            if(curNode == nullptr)
                continue;
            nodeStack.push(curNode->left);
            nodeStack.push(curNode->right);
            swap(curNode->left, curNode->right);
        }
        return root;
    }
};

題目2 101. 對稱二叉樹

給你一個二叉樹的根節點 root , 檢查它是否軸對稱。

示例 1:

img

輸入:root = [1,2,2,3,4,4,3]
輸出:true

示例 2:

img

輸入:root = [1,2,2,null,3,null,3]
輸出:false

提示:

  • 樹中節點數目在範圍 [1, 1000]
  • -100 <= Node.val <= 100

思路

這道題就是將樹拆分為左右兩個子樹,對子樹進行相反方向的遍歷比較就行了,可以使用遞迴法和迭代法,思路是類似的我用的是迭代法。

迭代法

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(!root->left && !root->right)
            return true;
        stack<TreeNode*> nodeStack1, nodeStack2;
        nodeStack1.push(root->left);
        nodeStack2.push(root->right);
        while(!nodeStack1.empty() && !nodeStack2.empty())
        {
            TreeNode* lft = nodeStack1.top(),
                    * rht = nodeStack2.top();
            nodeStack1.pop();
            nodeStack2.pop();
            if(!lft && !rht)
            {
                continue;
            }
            if(!lft || !rht || lft->val != rht->val)
                return false;
#define PUSH(STACK, NODE, POSITION) \
            STACK.push(NODE->POSITION);
            PUSH(nodeStack1, lft, left);
            PUSH(nodeStack1, lft, right);
            PUSH(nodeStack2, rht, right);
            PUSH(nodeStack2, rht, left);
#undef PUSH
        }
        return nodeStack1.empty() && nodeStack2.empty();
    }

題目3 104. 二叉樹的最大深度

給定一個二叉樹 root ,返回其最大深度。

二叉樹的 最大深度 是指從根節點到最遠葉子節點的最長路徑上的節點數。

示例 1:

img

輸入:root = [3,9,20,null,null,15,7]
輸出:3

示例 2:

輸入:root = [1,null,2]
輸出:2

提示:

  • 樹中節點的數量在 [0, 104] 區間內。
  • -100 <= Node.val <= 100

思路

這道題可以用遞迴法(前,後序遍歷)或者迭代法(層序遍歷)來計算出深度,基礎題。

遞迴法

/**
 * 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 Nextdepth(TreeNode* root)
    {
        if(!root)
        {
            return 0;
        }
        return 1 + max(Nextdepth(root->left), Nextdepth(root->right));
    }
    int maxDepth(TreeNode* root) {
        return Nextdepth(root);
    }
};

迭代法

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(!root)
            return 0;
        queue<TreeNode*> nodeQueue;
        nodeQueue.push(root);
        int depth = 0;
        while(!nodeQueue.empty())
        {
            int num = nodeQueue.size();
            for(int i = 0; i < num; i++)
            {
                TreeNode* node = nodeQueue.front();
                nodeQueue.pop();
                if(node->left)
                    nodeQueue.push(node->left);
                if(node->right)
                    nodeQueue.push(node->right);
            }
            depth++;
        }
        return depth;
    }
};

題目4 111. 二叉樹的最小深度

給定一個二叉樹,找出其最小深度。

最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。

說明:葉子節點是指沒有子節點的節點。

示例 1:

img

輸入:root = [3,9,20,null,null,15,7]
輸出:2

示例 2:

輸入:root = [2,null,3,null,4,null,5,null,6]
輸出:5

提示:

  • 樹中節點數的範圍在 [0, 105]
  • -1000 <= Node.val <= 1000

思路

和最大深度類似考察基本功,用遞迴法遍歷每一個結點獲取最小深度之後累加得到結果;或者用層序遍歷迭代到最淺的無雙child節點終止。

遞迴法

class Solution {
public:
    int NextDepth(TreeNode* root)
    {
        if(!root)
            return 0;
        if(!root->left && root->right)
            return 1 + NextDepth(root->right);
        if(root->left && !root->right)
            return 1 + NextDepth(root->left);
        return 1 + min(NextDepth(root->left), NextDepth(root->right));
    }
    int minDepth(TreeNode* root) {
        if(!root)
            return 0;
        return NextDepth(root);
    }
};

迭代法

class Solution {
public:
    int minDepth(TreeNode* root) {
        if(!root)
            return 0;
        queue<TreeNode*> nodeQueue;
        nodeQueue.push(root);
        int result = 0;
        while(!nodeQueue.empty())
        {
            int num = nodeQueue.size();
            for(int i = 0; i < num; i++)
            {
                TreeNode* curNode = nodeQueue.front();
                nodeQueue.pop();
                //若節點無左右child,則為最淺的節點,返回最小深度
                if(!curNode->left && !curNode->right)
                {
                    return result + 1;
                }
                if(curNode->left)
                    nodeQueue.push(curNode->left);
                if(curNode->right)
                    nodeQueue.push(curNode->right);
            }
            result++;
        }
        return result;
    }
};

相關文章