路径总和题型整理

这篇博客介绍了如何使用深度优先搜索(DFS)、广度优先搜索(BFS)以及回溯法解决二叉树路径和问题。提供了三种不同的实现方式,包括递归的DFS、使用队列的BFS以及类回溯法。对于DFS,展示了两种不同的实现思路。同时,还探讨了回溯法的两种模板应用,以及如何利用BFS找到所有满足条件的路径。文章通过代码实例详细解析了每种方法的工作原理和步骤。
摘要由CSDN通过智能技术生成

题型1:easy
在这里插入图片描述
在这里插入图片描述
深度优先搜索
在这里插入图片描述

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

在这里插入图片描述
广度优先搜索

  • 记录根节点到每个节点的路径总和,防止重复计算
 
class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum)
    {
        if (root == NULL) 
            return false;
        queue<pair<TreeNode*, int>> q;
        q.push({ root,root->val });
        while (!q.empty())
        {
            int sum = q.front().second;
            TreeNode* temp = q.front().first;
            q.pop();
            if (!temp->left && !temp->right)
            {
                if(sum==targetSum)
                return true;
                continue;
            }
            //同时朝着当前根节点的左右子树探索
            //探索的同时记录根节点到每个节点的路径和
            if (temp->left)
                q.push({ temp->left,temp->left->val + sum });
            if (temp->right)
                q.push({ temp->right,temp->right->val+sum });
        }
        return false;
    }
};

在这里插入图片描述
类回溯法

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum)
    {
        if (root == NULL) 
            return false;
        return backTravel(root,targetSum,root->val);
    }
    bool backTravel(TreeNode* root,int targetSum,int sum)
    {
        bool Lfind=false, Lright=false;
        if (!root) return false;
        if (!root->left && !root->right &&sum == targetSum)
            return true;
        if (root->left)
              Lfind=backTravel(root->left, targetSum, sum+root->left->val);
        if (root->right)
              Lright = backTravel(root->right, targetSum, sum+root->right->val);
        return Lfind || Lright;
    }
};

在这里插入图片描述
题型2:medium
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
回溯模板解题

class Solution {
  public:
      vector<vector<int>> pathSum(TreeNode* root, int targetSum) 
      {
          vector<vector<int>> ret;
          if (root == NULL)
              return ret;
          vector<int> cur;
          backTrave(ret,cur,root, targetSum);
          return ret;
      }
      void backTrave(vector<vector<int>>& ret, vector<int>& cur, TreeNode* root, int targetSum)
      {
          if (root == NULL) return;
          if (root->left == NULL && root->right == NULL)
          {
              cur.push_back(root->val);
              if (accumulate(cur.begin(), cur.end(), 0) == targetSum)
                  ret.push_back(cur);
              //如果当前是找到了一个解,那么回溯,寻找其他可能解
              //如果当前节点是叶子节点,那么再往下找,也不会得到正确解,也需要回溯
              cur.pop_back();
              return;
          }
          else
          {
              cur.push_back(root->val);
              //先从左子树开始找,如果无法找到合适解,去右子树里面找
              //如果左子树里面找到了合适解,要去右子树里面找还有无其他合适解
              backTrave(ret, cur, root->left, targetSum);
              backTrave(ret, cur, root->right, targetSum);
              //如果当前左右子树都无法找到合适解,说明当前根的两个分支走不通,需要返回上一层,寻找别的路径走
              //那么进行回溯,来到上一层,走另一个分支,即如果当前根是上一层的左子树,那么回到上一层后需要到右子树里面寻找可能解
              cur.pop_back();
          }
      }
  };

在这里插入图片描述
回溯模板第二种简化写法

class Solution {
public:
    vector<vector<int>> ret;
    vector<int> path;

    void dfs(TreeNode* root, int sum) {
        if (root == nullptr) {
            return;
        }
        path.emplace_back(root->val);
        sum -= root->val;
        if (root->left == nullptr && root->right == nullptr && sum == 0) {
            ret.emplace_back(path);
        }
        dfs(root->left, sum);
        dfs(root->right, sum);
        path.pop_back();
    }

    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        dfs(root, sum);
        return ret;
    }
};

在这里插入图片描述
广度优先遍历—BFS

  • 先来看看BFS的两个模板
  • 模板一:如果不需要确定当前遍历到了哪一层,BFS模板如下
while queue 不空:
    cur = queue.pop()
    if cur 有效且未被访问过:
        进行处理
    for 节点 in cur 的所有相邻节点:
        if 该节点有效:
            queue.push(该节点)
  • 模板二:如果要确定当前遍历到了哪一层,BFS模板如下。
    这里增加了level表示当前遍历到二叉树中的哪一层了,也可以理解为在一个图中,现在已经走了多少步了。size表示在当前遍历层有多少个元素,也就是队列中的元素数,我们把这些元素一次性遍历完,即把当前层的所有元素都向外走了一步。
level = 0
while queue 不空:
    size = queue.size()
    while (size --) {
        cur = queue.pop()
        if cur 有效且未被访问过:
            进行处理
        for 节点 in cur的所有相邻节点:
            if 该节点有效:
                queue.push(该节点)
    }
    level ++;

上面两个是通用模板,在任何题目中都可以用,是要记住的!

  • 本题的解法:本题要求所有的路径,不需要按层遍历,因此使用模板一。
  • 我们也可以采用广度优先搜索的方式,遍历这棵树。当我们遍历到叶子节点,且此时路径和恰为目标和时,我们就找到了一条满足条件的路径。
  • 为了节省空间,我们使用哈希表记录树中的每一个节点的父节点。每次找到一个满足条件的节点,我们就从该节点出发不断向父节点迭代,即可还原出从根节点到当前节点的路径。
class Solution {
public:
    vector<vector<int>> ret;
    unordered_map<TreeNode*, TreeNode*> parent;

    void getPath(TreeNode* node) {
        vector<int> tmp;
        while (node != nullptr) {
            tmp.emplace_back(node->val);
            node = parent[node];
        }
        reverse(tmp.begin(), tmp.end());
        ret.emplace_back(tmp);
    }

    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        if (root == nullptr) {
            return ret;
        }

        queue<TreeNode*> que_node;
        queue<int> que_sum;
        que_node.emplace(root);
        que_sum.emplace(0);

        while (!que_node.empty()) {
            TreeNode* node = que_node.front();
            que_node.pop();
            int rec = que_sum.front() + node->val;
            que_sum.pop();

            if (node->left == nullptr && node->right == nullptr) {
                if (rec == sum) {
                    getPath(node);
                }
            } else {
                if (node->left != nullptr) {
                    parent[node->left] = node;
                    que_node.emplace(node->left);
                    que_sum.emplace(rec);
                }
                if (node->right != nullptr) {
                    parent[node->right] = node;
                    que_node.emplace(node->right);
                    que_sum.emplace(rec);
                }
            }
        }

        return ret;
    }
};

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 目标检测的定义 目标检测(Object Detection)的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,是计算机视觉领域的核心问题之一。由于各类物体有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具有挑战性的问题。 目标检测任务可分为两个关键的子任务,目标定位和目标分类。首先检测图像中目标的位置(目标定位),然后给出每个目标的具体类别(目标分类)。输出结果是一个边界框(称为Bounding-box,一般形式为(x1,y1,x2,y2),表示框的左上角坐标和右下角坐标),一个置信度分数(Confidence Score),表示边界框中是否包含检测对象的概率和各个类别的概率(首先得到类别概率,经过Softmax可得到类别标签)。 1.1 Two stage方法 目前主流的基于深度学习的目标检测算法主要分为两类:Two stage和One stage。Two stage方法将目标检测过程分为两个阶段。第一个阶段是 Region Proposal 生成阶段,主要用于生成潜在的目标候选框(Bounding-box proposals)。这个阶段通常使用卷积神经网络(CNN)从输入图像中提取特征,然后通过一些技巧(如选择性搜索)来生成候选框。第二个阶段是分类和位置精修阶段,将第一个阶段生成的候选框输入到另一个 CNN 中进行分类,并根据分类结果对候选框的位置进行微调。Two stage 方法的优点是准确度较高,缺点是速度相对较慢。 常见Tow stage目标检测算法有:R-CNN系列、SPPNet等。 1.2 One stage方法 One stage方法直接利用模型提取特征值,并利用这些特征值进行目标的分类和定位,不需要生成Region Proposal。这种方法的优点是速度快,因为省略了Region Proposal生成的过程。One stage方法的缺点是准确度相对较低,因为它没有对潜在的目标进行预先筛选。 常见的One stage目标检测算法有:YOLO系列、SSD系列和RetinaNet等。 2 常见名词解释 2.1 NMS(Non-Maximum Suppression) 目标检测模型一般会给出目标的多个预测边界框,对成百上千的预测边界框都进行调整肯定是不可行的,需要对这些结果先进行一个大体的挑选。NMS称为非极大值抑制,作用是从众多预测边界框中挑选出最具代表性的结果,这样可以加快算法效率,其主要流程如下: 设定一个置信度分数阈值,将置信度分数小于阈值的直接过滤掉 将剩下框的置信度分数从大到小排序,选中值最大的框 遍历其余的框,如果和当前框的重叠面积(IOU)大于设定的阈值(一般为0.7),就将框删除(超过设定阈值,认为两个框的里面的物体属于同一个类别) 从未处理的框中继续选一个置信度分数最大的,重复上述过程,直至所有框处理完毕 2.2 IoU(Intersection over Union) 定义了两个边界框的重叠度,当预测边界框和真实边界框差异很小时,或重叠度很大时,表示模型产生的预测边界框很准确。边界框A、B的IOU计算公式为: 2.3 mAP(mean Average Precision) mAP即均值平均精度,是评估目标检测模型效果的最重要指标,这个值介于0到1之间,且越大越好。mAP是AP(Average Precision)的平均值,那么首先需要了解AP的概念。想要了解AP的概念,还要首先了解目标检测中Precision和Recall的概念。 首先我们设置置信度阈值(Confidence Threshold)和IoU阈值(一般设置为0.5,也会衡量0.75以及0.9的mAP值): 当一个预测边界框被认为是True Positive(TP)时,需要同时满足下面三个条件: Confidence Score > Confidence Threshold 预测类别匹配真实值(Ground truth)的类别 预测边界框的IoU大于设定的IoU阈值 不满足条件2或条件3,则认为是False Positive(FP)。当对应同一个真值有多个预测结果时,只有最高置信度分数的预测结果被认为是True Positive,其余被认为是False Positive。 Precision和Recall的概念如下图所示: Precision表示TP与预测边界框数量的比值 Recall表示TP与真实边界框数量的比值 改变不同的置信度阈值,可以获得多组Precision和Recall,Recall放X轴,Precision放Y轴,可以画出一个Precision-Recall曲线,简称P-R
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值