LeetCode 112. 路径总和 、113. 路径总和 II 思考分析

目录

  • 112. 路径总和
    • 题目
    • 递归解
    • 递归解,其他人的解法
    • 迭代解,其他人的解法
  • 113. 路径总和 II
    • 题目
    • 递归解
    • 递归解,参考别人的思路

112. 路径总和

题目

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

说明: 叶子节点是指没有子节点的节点。

示例:
给定如下二叉树,以及目标和 sum = 22,
在这里插入图片描述
返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。

递归解

1、函数参数:当前树的根结点、当前累积的路径和,目标路径和;返回值为空
2、终止条件:该结点为空
3、单层逻辑:如果该结点不为空,则在累积路径和上加上该结点的值。如果该结点是叶子结点,判断此时的累积路径和与目标路径和是否相同,如果相同则将全局变量ifHas改为true,认为能够找到路径和为目标值的路径。然后返回父结点,回溯到上一个状态,参数会自动更正为上一个状态的参数。接下来就是按顺序对该结点的左右孩子进行遍历

这个思路是有问题的,因为它只在叶子结点之后才回溯,这是不合理的,但是也能AC。

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
public:bool ifHas=false;void traversal(TreeNode* cur,int target,int Mysum){if(cur==NULL)  return;if(cur!=NULL)  Mysum+=cur->val;//如果是叶子结点,则进行比较if(cur->left==NULL && cur->right==NULL){//如果和目标结果相同if(Mysum == target) ifHas=true;return;}if(cur->left){traversal(cur->left,target,Mysum);}if(cur->right){traversal(cur->right,target,Mysum);}return ;}bool hasPathSum(TreeNode* root, int sum) {//if(root == NULL) return false;int Mysum=0;traversal(root,sum,Mysum);return ifHas;}
};

在这里插入图片描述

递归解,其他人的解法

1、函数参数、返回值确定
之前有个结论:如果需要搜索整棵二叉树,那么递归函数就不要返回值,如果要搜索其中一条符合条件的路径,递归函数就需要返回值,因为遇到符合条件的路径就要及时返回
本题并不需要遍历整棵树,所以递归函数需要返回值,可以用bool类型表示。

bool traversal(TreeNode* cur,int count)		

2、终止条件确定
在如何统计一条路径和的方法上,代码随想录使用递减的方法,让计数器count初始为目标和,然后每次减去遍历路径结点上的数值。如果最后count==0,同时到了叶子结点的话,说明了找到目标和。如果遍历到了叶子结点,cout不为0,就是没找到

if(!cur->left && !cur->right && count == 0) return true;		//遇到叶子结点,并且计数为0
if(!cur->left && !cur->right) return false;					//遇到叶子结点,没有找到合适的边,直接返回

3、确定单层递归的逻辑
因为终止条件是判断也自己诶单,所以递归过程中就不要让空结点进入递归了。
递归函数的返回值为true的话说明了找到了合适的路径,应该立刻返回

if(cur->left)
{count -=cur->left->val;//遇到叶子结点返回true,则直接返回true;if(traversal(cur->left,count)) return true;count +=cur->left->val;			//回溯,撤销处理结果
}
if(cur->right)
{count -=cur->right->val;//遇到叶子结点返回true,则直接返回true;if(traversal(cur->right,count)) return true;count +=cur->right->val;			//回溯,撤销处理结果
}
return false;
class Solution {
public:bool traversal(TreeNode* cur,int count)		{if(!cur->left && !cur->right && count == 0) return true;		//遇到叶子结点,并且计数为0if(!cur->left && !cur->right) return false;					//遇到叶子结点,没有找到合适的边,直接返回if(cur->left){count -=cur->left->val;//遇到叶子结点返回true,则直接返回true;if(traversal(cur->left,count)) return true;count +=cur->left->val;			//回溯,撤销处理结果}if(cur->right){count -=cur->right->val;//遇到叶子结点返回true,则直接返回true;if(traversal(cur->right,count)) return true;count +=cur->right->val;			//回溯,撤销处理结果}return false;}bool hasPathSum(TreeNode* root, int sum) {if(root == NULL) return false;return traversal(root,sum-root->val);}
};

迭代解,其他人的解法

如果使用栈模拟递归的话对于回溯如何处理?
此时栈里面的一个元素不仅要记录该结点指针,还要记录从头结点到该结点的路径数值总和。
这里使用pair结构来存放栈里面的元素。(第一次用这个结构)
定义为:

pair<TreeNode*,int> pair<结点指针,路径数值>

为栈中的一个元素。
使用栈模拟前序遍历;

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
public:bool hasPathSum(TreeNode* root, int sum) {if(root == NULL) return false;//此时栈里面要放的是pair<结点指针,路径数值>stack<pair<TreeNode*,int>> st;st.push(pair<TreeNode*,int>(root,root->val));while(!st.empty()){pair<TreeNode*,int> node = st.top();st.pop();//如果这个结点是叶子结点,同时该结点的路径数值等于sum,那么就返回trueif(!node.first->left &&!node.first->right && sum == node.second ) return true;//右结点,压进去一个结点的时候,将该结点的路径数值也记录下来if(node.first->right){st.push(pair<TreeNode*,int>(node.first->right,node.second+node.first->right->val));}//右结点,压进去一个结点的时候,将该结点的路径数值也记录下来if(node.first->left){st.push(pair<TreeNode*,int>(node.first->left,node.second+node.first->left->val));}}return false;}
};

113. 路径总和 II

题目

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

说明: 叶子节点是指没有子节点的节点。
在这里插入图片描述

递归解

同样的道理,Mysum作为函数参数每次返回的时候会自动更正,不需要手动回溯。
完成一次子结果,就将子结果送入paths中。
path需要手动回溯。

 path.push_back(cur->left->val);traversal(cur->left,target,Mysum);path.pop_back();

同时需要注意,在一开始要将根结点送入path中,因为在我们的递归函数中只对左右孩子进行push_back()

class Solution {
public:vector<vector<int>> paths;vector<int> path;void traversal(TreeNode* cur,int target,int Mysum){if(cur==NULL)  return;if(cur!=NULL){Mysum+=cur->val;}  //如果是叶子结点,则进行比较if(cur->left==NULL && cur->right==NULL){//如果和目标结果相同if(Mysum == target){paths.push_back(path);}return;}if(cur->left){path.push_back(cur->left->val);traversal(cur->left,target,Mysum);path.pop_back();}if(cur->right){path.push_back(cur->right->val);traversal(cur->right,target,Mysum);path.pop_back();}return ;}vector<vector<int>> pathSum(TreeNode* root, int sum) {if(root==NULL) return {};int Mysum=0;path.push_back(root->val);traversal(root,sum,Mysum);return paths;}
};

递归解,参考别人的思路

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
private:vector<vector<int>> paths;vector<int> path;//递归函数不需要返回值,因为我们要遍历整个树void traversal(TreeNode* cur,int count){if(!cur->left && !cur->right && count == 0)     //遇到了叶子结点且找到了和为sum的路径{paths.push_back(path);return;}if(!cur->left && !cur->right ) return;if(cur->left){path.push_back(cur->left->val);count-=cur->left->val;traversal(cur->left,count);count+=cur->left->val;path.pop_back();}if(cur->right){path.push_back(cur->right->val);count-=cur->right->val;traversal(cur->right,count);count+=cur->right->val;path.pop_back();}return;}
public:vector<vector<int>> pathSum(TreeNode* root, int sum) {paths.clear();path.clear();if(root==NULL) return paths;path.push_back(root->val);traversal(root,sum-root->val);return paths;}
};

工程实践上一定要clear,但是由于力扣后台测试数据,每次都是新new一个对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/377968.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kotlin 查找id_Kotlin程序查找矩阵的转置

kotlin 查找idA transpose of a matrix is simply a flipped version of the original matrix. We can transpose a matrix by switching its rows with its columns 矩阵的转置只是原始矩阵的翻转形式。 我们可以通过切换矩阵的行和列来转置矩阵 Given a matrix, we have to…

[mongodb翻译]分片和故障转移

一个配置恰当的mongodb 分片集群不会有单点失效。 本章节描述了集群服务器中可能出现的故障&#xff0c;及相应的对策。 1. 某个mongos路由进程故障 每一个mongos会运行每一台应用服务器上面&#xff0c;该应用服务器只能通过这个mongos进程和集群进行通信。mongos进程不是…

看张子阳的书真是收获很多,也醒悟了很多(一)

摘录&#xff1a; 这是有一次开会时&#xff0c;我的老总跟我们说了这样一个事例&#xff1a;通常来说&#xff0c;医生是很高尚的职业&#xff08;暂不考虑国内医生的负面新闻&#xff09;&#xff0c;尤其是牙科医生&#xff0c; 他们有着体面的工作并且收入不菲。但是&#…

【C++ grammar】抽象、封装与this指针

目录1、Abstraction and Encapsulation&#xff08;抽象与封装&#xff09;1. Data Field Encapsulation (数据域封装)2. Accessor and Mutator (访问器与更改器)2.1. To read/write private data, we need get/set function (为读写私有数据&#xff0c;需要get/set函数)2.2. …

java创建临时文件_用Java创建一个临时文件

java创建临时文件The task is to create a temporary file in Java. 任务是用Java创建一个临时文件。 Creating a temporary file 创建一个临时文件 To create a temporary file in java – we use createTempFile() method of "File" class. The createTempFile()…

十九、图像的形态学操作

一、图像形态学 图像形态学是图像处理学科的一个单独分支学科 主要针对的是灰度图和二值图像 是由数学的集合论以及数学中的拓扑几何原理发展而来 二、膨胀操作&#xff08;dilate&#xff09; 33的卷积核 以33为卷积核从左往右(从上往下)开始运行&#xff0c;若这卷积核…

X名称空间(WPF)

笔记简述 闲话x名称空间简要x名称空间的Attributex名称空间的标签扩展x名称空间的XAML指令元素闲话 本笔记参考与《深入浅出WPF》、MSDN、Some Blog… MSDN的飞机票点这里。 x名称空间简要 在VS中新建个WpfApplication都会自动生成xmlns:x"http://schemas.microsoft.com/w…

基于Bresenham和DDA算法画线段

直线&#xff1a;ykxb 为了将他在显示屏上显示出来&#xff0c;我们需要为相应的点赋值&#xff0c;那么考虑到计算机的乘法执行效率&#xff0c;我们肯定不会选择用Ykxb这个表达式求值&#xff0c;然后进行画线段。 我们应当是将它转化为加法运算。 下面提供两种常见的算法&am…

leetcode 106. 从中序与后序遍历序列构造二叉树 105. 从前序与中序遍历序列构造二叉树思考分析

目录1、106题目2、参考思路&#xff1a;递归切割数组3、105题目4、同样思路的代码1、106题目 2、参考思路&#xff1a;递归切割数组 代码参考&#xff1a;公众号&#xff1a;代码随想录 后序数组中序数组 以 后序数组(左右中)的最后一个元素作为切割点&#xff0c;先切中序数组…

按频率对元素进行排序

Prerequisite: 先决条件&#xff1a; Hashing data structure 散列数据结构 How to write user-defined comparator for priority queue STL in C? 如何在C 中为优先级队列STL编写用户定义的比较器&#xff1f; How to sort a map based on values instead of value? 如何根…

二十、分水岭算法

一、基本原理 分水岭算法主要是基于距离变换&#xff08;distance transform&#xff09;&#xff0c;找到mark一些种子点&#xff0c;从这些种子点出发根据像素梯度变化进行寻找边缘并标记 分水岭&#xff1a;可以简单的理解成一座山&#xff0c;然后来洪水了&#xff0c;水开…

细数WOW里暴雪的“亲儿子”们

. 不知何时&#xff0c;魔兽世界的词汇中忽然出现了一个新玩意&#xff1a;亲儿子。虽说这个称呼现在大多是拿来调侃法爷的&#xff0c;但江山代有儿子出&#xff0c;各领风骚一两天&#xff0c;今天风光无限的法爷们也经历过被其他职业压得抬不起头的小媳妇生涯。那么今天…

Linux下串口ttyS2,ttyS3不能用的问题解决办法

PC104&#xff0c;Xlinux下&#xff0c;突然发现串口3,4不能用。。。 以为是硬件的问题&#xff0c;换成wince后&#xff0c;3,4工作正常&#xff0c;排除电路问题 在linux下查看dmesg: serial8250: ttyS0 at I/O 0x3f8 (irq 4) is a 16550Aserial8250: ttyS1 at I/O 0x2f8 (i…

安卓log.e函数打印示例_log1p()函数以及C ++中的示例

安卓log.e函数打印示例C log1p()函数 (C log1p() function) log1p() function is a library function of cmath header, it is used to get the natural logarithm (the base-e logarithm) of the one plus given value. It accepts a value (float, double, or long double) …

【C++grammar】C++类数据成员的初始化

目录1、类成员的就地初始化example2、构造函数初始化3、默认构造函数&#xff1a;Default Constructor4、举例5、成员的初始化方法的优先级1、类成员的就地初始化example class S { int m 7; // ok, copy-initializes m int n(7); // 错误&#xff1a;不允许用小括号初始化…

二十一、人脸检测

一、识别图像中的人脸 haarcascade_frontalface_alt_tree.xml lbpcascade_frontalcatface.xml GitHub上有Haar级联检测器源代码可自行下载&#xff0c;lbp级联检测器也一样有源码可自行下载 也一样 import cv2 as cv import numpy as npdef face_detect(image):gray cv.cvtC…

aspx特殊符号说明

http://www.cnblogs.com/GnagWang/archive/2010/07/14/1777130.html转载于:https://www.cnblogs.com/mingyongcheng/archive/2011/11/24/2261253.html

javascript运算符_JavaScript中的按位运算符

javascript运算符JavaScript按位运算符 (JavaScript Bitwise Operators) A lot of times you come across some strange operators where youre knocking your head to understand what is going on in the code. Almost all the programming languages have bitwise operators…

[置顶] Android的IPC访问控制设计与实现

3.3.1 IPC钩子函数设计与实现 IPC Binder是Android最重要的进程间通信机制&#xff0c;因此&#xff0c;必须在此实施强制访问控制。 1. 修改secuirty.h 打开终端shell&#xff0c;输入指令“cd /android4.0/kernel/goldfish/include/linux/vim security.h”&#xff0c;找到结…

TensorFlow在Anaconda环境下创建

一、我使用的是Anaconda自带的Jupyter编译器&#xff0c;详细的安装教程可以参考博文 二、之后打开Jupyter 三、进行测试 我的tensorflow使用的是2.0版本 import tensorflow.compat.v1 as tf tf.disable_v2_behavior()a tf.constant([1.0,2.0],name"a") b tf.co…