Leetcode数据结构入门第十二天(树的应用(2))

226. 翻转二叉树

题目描述

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

样例

在这里插入图片描述

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

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

输入:root = []
输出:[]

思路一

递归法:这里翻转二叉树,其实本质上很简单,就是遍历二叉树的每个节点,把每个节点的左右孩子交换一下即可,所以不同方法本质是不同的遍历方式。这里使用的是递归法的先序遍历,递归终点是根节点为空,单层递归逻辑为:先序遍历:根-左-右,所以我们先交换根节点的左右孩子,然后通过递归分别翻转左子树和右子树。
(当然也可以写迭代法的前序遍历)

参考代码

/**
 * 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==NULL) return root;
        
        //处理单层递归逻辑:先交换左右子树的根节点,然后再分别翻转左右子树
        //相当于这里就是递归的先序遍历
        swap(root->left,root->right);//根
        invertTree(root->left);//左
        invertTree(root->right);//右
        return root;
    }
};

思路二

迭代法:先序遍历为根-左-右。
用栈存储遍历的节点,每次先处理根节点,出栈,交换根节点的左右孩子,再压入右孩子,左孩子,保证出栈顺序为左,右。

参考代码

/**
 * 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==NULL) return root;
        //栈:存储节点
        stack<TreeNode*> st;
        //压入根节点
        st.push(root);
       while(!st.empty())
       {
           //先处理根节点,出栈
           TreeNode* node=st.top();
           st.pop();
           swap(node->left,node->right);

           //压入右,左节点,这样保证栈顶为左节点
           if(node->right) st.push(node->right);
           if(node->left) st.push(node->left);
       }
        return root;
    }
};

112. 路径总和

题目描述

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。

样例

在这里插入图片描述

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。


思路一

递归法
递归终点:要么是叶子节点值=目标值,要么是根节点为空
单层递归逻辑:当前节点的左右子节点到叶子节点的目标值和为targetsum减去根当前节点值,只要有一个子节点满足要求,即可返回true,所以用或者即可。

参考代码

/**
 * 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:
    bool hasPathSum(TreeNode* root, int targetSum) {
        //递归终点:
        //根节点为空,直接返回
        if(root==NULL) return false;
        //遇到叶子结点,判断目标值与当前叶子结点是否相等
        else if(root->left==NULL&&root->right==NULL)
        {
            if(targetSum!=root->val) return false;
            else return true;
        } 
        
        //单层逻辑:
        //当前节点的子节点到叶子节点的目标值和为targetsum减去根当前节点值,
        bool left=hasPathSum(root->left,targetSum-root->val);
        bool right=hasPathSum(root->right,targetSum-root->val);
        //当前节点的左右子节点有一条路径满足即可
        return left||right;

    }
};

思路二

广度优先搜索(bfs):为了避免每次重复计算已经经历过的路径和,所以额外请求了一个队列用来存储到每个节点的路径和,如果到叶子节点,有路径和相等的就可以返回,否则继续。

参考代码

/**
 * 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:
    bool hasPathSum(TreeNode* root, int targetSum) {
        //bfs
        if(root==NULL) return false;
        queue<TreeNode*> que;
        queue<int> total;
        que.push(root);
        total.push(root->val);
        while(!que.empty())
        {
            int len=que.size();
            for(int i=0;i<len;i++)
            {
                //取得当前节点和前面节点和
                TreeNode* node=que.front();
                int temp=total.front();
                que.pop();
                total.pop();

                //判断出现叶子节点时,当前和是否已经满足条件
                if(!node->left&&!node->right)
                {
                    if(temp==targetSum) return true;
                }
                //压入子节点和含括子节点的节点值的路径和
                if(node->left)
                {
                    que.push(node->left);
                    total.push(node->left->val+temp);
                }
                if(node->right)
                {
                    que.push(node->right);
                    total.push(node->right->val+temp);
                }

            }
        }
        //循环结束还找不到满足的路径
        return false;

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值