Leetcode:112. 路径总和、113. 路径总和 II(C++)

目录

112. 路径总和:

问题描述:

实现代码与解析:

递归:

原理思路:

迭代:

原理思路:

113. 路径总和 II:

问题描述:

实现代码与解析:

迭代:

原理思路:


112. 路径总和:

问题描述:

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

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

示例 1:

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

示例 2:

输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。

示例 3:

输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。

实现代码与解析:

递归:

class Solution {
public:
    bool traversal(TreeNode* cur,int count)
    {
        if(cur==NULL) return false;
        count-=cur->val;//减去当前结点的值
        //走到了叶子结点
        if(cur->left==NULL&&cur->right==NULL)
        {
            //若到这里count减为0,返回true,反之返回false
            if(count==0) return true;
            else return false;
        }
        bool left=traversal(cur->left,count);
        bool right=traversal(cur->right,count);
        return left||right;

    }
    bool hasPathSum(TreeNode* root, int targetSum) 
    {
        bool result=traversal(root,targetSum);
        return result;
    }
};

精简版:

class solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) 
    {
        if (root == null) return false;
        if (!root->left && !root->right && targetSum == root->val) 
        {
            return true;
        }
        return haspathsum(root->left, targetSum - root->val) || haspathsum(root->right, targetSum - root->val);
    }
};

原理思路:

        这里我们不用一个个累加然后判断是否与sum相等,可以让count等于targetSum然后每到一个结点就减去该结点的值,判断count最后是否为0,就可以知道该路径符不符合要求了,然后注意每个判断条件返回的是false还是true我们返回的时候用的是 || 而不是我们常用的 && ,因为这里我们只要有一条路线符合条件就可以了。然后代码其实就是在遍历代码上添加一点上述的条件而已,就不详细解释了,大家看代码就能看懂。

迭代:

class Solution {
public:
    
    bool hasPathSum(TreeNode* root, int targetSum) 
    {
        if(root==NULL) return false;
        stack<pair<TreeNode*,int>> st;//放入<结点,路径值>
        st.push(pair<TreeNode*,int>(root,root->val));
        while(!st.empty())
        {
            pair<TreeNode*,int> temp=st.top();
            st.pop();
            //若为叶子结点,进行判断
            if(!temp.first->left&&!temp.first->right&&targetSum==temp.second) return true;
            if(temp.first->right)
            {
                st.push(pair<TreeNode*,int>(temp.first->right,temp.second+temp.first->right->val));
            }
            if(temp.first->left)
            {
                st.push(pair<TreeNode*,int>(temp.first->left,temp.second+temp.first->left->val));
            }
        }
        return false;
    }
};

原理思路:

        这里我们用pair<TreeNode*,int>的结构来入栈,记录结点指针和当前结点与根结点的路径长,然后到叶结点判断其路径长是否与目标targetSum相等即可。

113. 路径总和 II:

问题描述:

        给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

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

示例 1:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]

示例 2:

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

示例 3:

输入:root = [1,2], targetSum = 0
输出:[]

实现代码与解析:

迭代:

class Solution {
public:
    vector<vector<int>> result;//记录结果
    vector<int> path;   //记录路径
    void traversal(TreeNode* cur,int count)
    {
        if(cur->left==NULL&&cur->right==NULL)
        {
            //符合条件
            if(count==0)
            {
                result.push_back(path);
                return;
            }
            //不符合条件直接返回
            else
            {
                return;
            }            
        }
        //左不为空
        if(cur->left)
        {
            path.push_back(cur->left->val);
            traversal(cur->left,count-cur->left->val);//减去下一结点值,传入
            path.pop_back();
        }
        //右不为空
        if(cur->right)
        {
            path.push_back(cur->right->val);
            traversal(cur->right,count-cur->right->val);//减去下一结点值,传入
            path.pop_back();
        }
        return;
    }
    
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) 
    {
        if (root == NULL) return result;
        path.push_back(root->val);//先把头结点放入路径
        traversal(root,targetSum-root->val);
        return result;
    }
};

原理思路:

        与上一题原理相同,就是这里我们要求全部符合要求的路径,所以这里我们另外定义一个path来记录,递归时不用返回值。
 

给定一个整数数组 nums 和一个目标值 target,要求在数组中找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cosmoshhhyyy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值