首页 > 编程语言 >算法学习Day17二叉树迭迭迭迭代

算法学习Day17二叉树迭迭迭迭代

时间:2023-12-30 10:56:49浏览次数:44  
标签:node return 迭迭 res Day17 二叉树 root 节点 left

Day17迭迭迭迭代

By HQWQF 2023/12/28

笔记


110.平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树_每个节点_ 的左右两个子树的高度差的绝对值不超过 1 。

示例 1:

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

递归法

我们这里再复习下概念:
二叉树节点的深度:指从该节点到根节点的最长简单路径边的条数。
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。

关于根节点的深度究竟是1 还是 0,不同的地方有不一样的标准,力扣上是1。

为了判断每个节点的左右两个子树的高度差,我们需要获得子树的高度,在得出两个子树的高度差后我们可以判断是否绝对值超过 1,超过则通过引用参数给变量赋false。

递归法代码

class Solution {
public:
    bool isBalanced(TreeNode* root) {
        bool res = true;
        getdepth(root,res);
        return res;
    }
    int getdepth(TreeNode* node,bool &res)
    {
        if(node == nullptr){return 0;}
        int l = getdepth(node->left,res) + 1;
        int r = getdepth(node->right,res) + 1;
        if(abs(l-r) > 1){res = false;}
        return max(l,r);
    }
};

其实我们可以在碰到节点左右不平衡时用特殊的返回值进行标识,比如-1,只要有子树返回了-1,就继续返回-1,这样我们就可以省下一个参数了。

class Solution {
public:
    // 返回以该节点为根节点的二叉树的高度,如果不是平衡二叉树了则返回-1
    int getHeight(TreeNode* node) {
        if (node == NULL) {
            return 0;
        }
        int leftHeight = getHeight(node->left);
        if (leftHeight == -1) return -1;
        int rightHeight = getHeight(node->right);
        if (rightHeight == -1) return -1;
        return abs(leftHeight - rightHeight) > 1 ? -1 : 1 + max(leftHeight, rightHeight);
    }
    bool isBalanced(TreeNode* root) {
        return getHeight(root) == -1 ? false : true;
    }
};

迭代法

求高度需要一个回溯的过程,如果从叶子节点向上处理会容易一些,所以我们配合栈以实现类似回溯的效果来求一个节点的高度。

然后我们可以使用栈来对节点进行遍历,对每个节点的左右孩子求高度,不平衡就返回false.

迭代法代码

class Solution {
private:
    int getDepth(TreeNode* cur) {
        stack<TreeNode*> st;
        if (cur != NULL) st.push(cur);
        int depth = 0; // 记录深度
        int result = 0;
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                st.push(node);                          // 中
                st.push(NULL);
                depth++;
                if (node->right) st.push(node->right);  // 右
                if (node->left) st.push(node->left);    // 左

            } else {
                st.pop();
                node = st.top();
                st.pop();
                depth--;
            }
            result = result > depth ? result : depth;
        }
        return result;
    }

public:
    bool isBalanced(TreeNode* root) {
        stack<TreeNode*> st;
        if (root == NULL) return true;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();                       // 中
            st.pop();
            if (abs(getDepth(node->left) - getDepth(node->right)) > 1) {
                return false;
            }
            if (node->right) st.push(node->right);           // 右(空节点不入栈)
            if (node->left) st.push(node->left);             // 左(空节点不入栈)
        }
        return true;
    }
};

注释

  • 递归时,如果是利用递归去深入,代码里写fun(node,deep+1),如果是利用递归去回溯,代码里写fun(node) + 1
  • 其实这里的迭代法的效率比递归慢不少,但是递归本身就是用栈实现的啊,那是不是说有比这个迭代法更快的迭代法呢?

257.二叉树的所有路径

class Solution {
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> resList;
        string res ="";
        test(root,res,resList);
        return resList;
    }
    void traversal(TreeNode* node,string res,vector<string> &resList)
    {
        if(node->left == nullptr && node->right == nullptr)
        {
            resList.push_back(res + to_string(node->val));
            return;
        }
        if(node->left)
            traversal(node->left,res + to_string(node->val)+ "->",resList);
        if(node->right)
            traversal(node->right,res +  to_string(node->val)+ "->",resList);
    }
};

迭代法

迭代法我们可以在栈遍历节点的基础上,使用一个和节点栈结构类似的路径栈来存储根节点到当前节点的路径,在遍历到下一个节点时会通过当前节点在路径栈中的值设置下一个节点在路径栈中对应的值,一样是碰到叶子就把路径加入链表。

迭代法代码

class Solution {
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        stack<TreeNode*> treeSt;// 保存树的遍历节点
        stack<string> pathSt;   // 保存遍历路径的节点
        vector<string> result;  // 保存最终路径集合
        if (root == NULL) return result;
        treeSt.push(root);
        pathSt.push(to_string(root->val));
        while (!treeSt.empty()) {
            TreeNode* node = treeSt.top(); treeSt.pop(); // 取出节点 中
            string path = pathSt.top();pathSt.pop();    // 取出该节点对应的路径
            if (node->left == NULL && node->right == NULL) { // 遇到叶子节点
                result.push_back(path);
            }
            if (node->right) { // 右
                treeSt.push(node->right);
                pathSt.push(path + "->" + to_string(node->right->val));
            }
            if (node->left) { // 左
                treeSt.push(node->left);
                pathSt.push(path + "->" + to_string(node->left->val));
            }
        }
        return result;
    }
};

404.左叶子之和

给定二叉树的根节点 root ,返回所有左叶子之和。

示例 1:

输入: root = [3,9,20,null,null,15,7]
输出: 24
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24

递归法

比较常规,通过遍历检测左叶子,检测到就累加其值到引用变量中。

注意如果当前节点的左孩子是叶子节点的话,就不用往当前节点的左支递归了,把左支递归的语句写在else还会快点。

递归法代码

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        int res = 0;
        traversal(root,res);
        return res;
    }
    void traversal(TreeNode* node,int &res)
    {
        if(node->left != nullptr && node->left->left == nullptr && node->left->right == nullptr)
        {
            res += node->left->val;
        }else
        {
            if(node->left)traversal(node->left,res);
        }
        if(node->right)traversal(node->right,res);
        if( node->left== nullptr && node->right == nullptr){return;}
    }
};

还是只用一个函数的最优雅,只用一个函数就必须要用返回值了,我们可以这样设定,根节点下的左叶子数等于其子树的左叶子数之和,我们可以一路递归深入,如果碰到左叶子就返回左叶子的值,不然就返回0,每个节点都向上返回自己为根的子树的局部左叶子之和

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        if (root == NULL) return 0;
        int leftValue = 0;
        if (root->left != NULL && root->left->left == NULL && root->left->right == NULL) {
            leftValue = root->left->val;
        }
        return leftValue + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
    }
};

迭代法还是遍历,然后判断,没什么好提的。

标签:node,return,迭迭,res,Day17,二叉树,root,节点,left
From: https://www.cnblogs.com/HQWQF/p/17936130.html

相关文章

  • 代码随想录算法训练营第十七天 | 110.平衡二叉树,257. 二叉树的所有路径,404.左叶子之和
    一、110.平衡二叉树题目链接:LeetCode110.平衡二叉树学习:思路:后序遍历。实际上是由叶结点到根结点,若有一颗子树不是平衡二叉树,则直接返回给根结点二、257.二叉树的所有路径题目链接:LeetCode257.二叉树的所有路径学习:思路:递归+回溯。因为是线=先遍历根结点,然后遍历左孩......
  • 二叉树和哈夫曼树
    Entropy(poj1521)题目大意对字符串分别用ASCII编码(每个字符8b)和哈夫曼编码,输出编码前、后的长度并计算压缩比。解题思路本题不要求求出编码,只需计算长度,考虑记录字符出现频次,用优先队列记录最小的两个频次,直接计算长度。未知的代码#include<bits/stdc++.h>usingnamespa......
  • 代码随想录算法训练营第十六天 |104.二叉树的最大深度,559.n叉树的最大深度,111.二叉树
    一、104.二叉树的最大深度题目链接:LeetCode104.二叉树的最大深度学习:思路:分别求左子树和右子树的高度,返回给根结点,加1之后是根结点的深度,这是后序遍历的思路二、559.n叉树的最大深度题目链接:LeetCode559.N叉树的最大深度学习前:思路:后序遍历。分别所有孩子结点的深......
  • 114. 二叉树展开为链表
    给你二叉树的根结点 root ,请你将它展开为一个单链表:展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。 示例1:输入:root=[1,2,5,3,4,null,6]输出:[1,null,2,null,3,......
  • 代码随想录算法训练营第十五天 | 层序遍历 ,226.翻转二叉树,101.对称二叉树
    一、二叉树层序遍历题目链接:LeetCode102.二叉树的层序遍历LeetCode107.二叉树的层序遍历IILeetCode199.二叉树的右视图LeetCode637.二叉树的层平均值LeetCode429.N叉树的层序遍历LeetCode515.在每个树行中找最大值LeetCode116.填充每个节点的下一个右侧节......
  • [LeetCode Hot 100] LeetCode102. 二叉树的层序遍历
    题目描述思路方法一:递归/***Definitionforabinarytreenode.*publicclassTreeNode{*intval;*TreeNodeleft;*TreeNoderight;*TreeNode(){}*TreeNode(intval){this.val=val;}*TreeNode(intval,TreeNodelef......
  • [LeetCode Hot 100] LeetCode543. 二叉树的直径
    题目描述思路所谓二叉树的直径,就是左右子树的最大深度之和。方法一:/***Definitionforabinarytreenode.*publicclassTreeNode{*intval;*TreeNodeleft;*TreeNoderight;*TreeNode(){}*TreeNode(intval){this.val=va......
  • [LeetCode Hot 100] LeetCode104. 二叉树的最大深度
    题目描述思路熟练掌握二叉树的遍历算法方法一:层序遍历(迭代)+计数/***Definitionforabinarytreenode.*publicclassTreeNode{*intval;*TreeNodeleft;*TreeNoderight;*TreeNode(){}*TreeNode(intval){this.val=val;......
  • [LeetCode Hot 100] LeetCode110. 平衡二叉树
    题目描述思路LeetCode104.二叉树的最大深度变种方法一:后序遍历(递归、dfs)/***Definitionforabinarytreenode.*publicclassTreeNode{*intval;*TreeNodeleft;*TreeNoderight;*TreeNode(){}*TreeNode(intval){this.......
  • [LeetCode Hot 100] LeetCode111. 二叉树的最小深度
    题目描述思路二叉树的最小深度就是第一个叶子节点所在的层数方法一:前序遍历(递归、dfs)/***Definitionforabinarytreenode.*publicclassTreeNode{*intval;*TreeNodeleft;*TreeNoderight;*TreeNode(){}*TreeNode(intva......