目录
路径总和I.II.III(112.113.437)
112.路径总和.II.III(112.113.437)
给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
说明: 叶子节点是指没有子节点的节点。
示例:
给定如下二叉树,以及目标和sum = 22
,5 / \ 4 8 / / \ 11 13 4 / \ \ 7 2 1 返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。
解法:从根节点递归到叶子节点,依次相加,得到一个与sum一样的值则返回true,否则继续递归,直到树空
/**
* Definition for a binary tree node.
* class TreeNode {
* public $val = null;
* public $left = null;
* public $right = null;
* function __construct($value) { $this->val = $value; }
* }
*/
class Solution {
function hasPathSum($root, $sum) {
if($root == null) return false; //当树为空时,直接返回false
if($root->left == null && $root->right == null) return $root->val == $sum; //当值等于sum时,即已找到结果
//递归左右子树,参数sum = 当前的sum - 当前节点(即下一节点的父节点)的值
return $this->hasPathSum($root->left, $sum - $root->val) || $this->hasPathSum($root->right, $sum - $root->val);
}
}
113.路径总和II
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
给定如下二叉树,以及目标和sum = 22
,5 / \ 4 8 / / \ 11 13 4 / \ / \ 7 2 5 1 返回:[ [5,4,11,2], [5,8,4,5] ]
与112区别:该题需要额外记录满足条件的所有路径
class Solution {
function pathSum($root, $sum) {
if($root == null) return []; //当树为空时,返回空数组
$res = [];
$this->getAllPath($root,$sum,[],$res); //递归函数:获得所有路径
return $res;
}
public function getAllPath($root,$sum,$path,&$res){
//参数(节点,剩余的sum,已经取得的路径序列,引用传值结果数组)
if($root == null) return; //树为空,直接返回
$num = $root->val; //将节点的值压入路径中,方便之后使用
$path[] = $num;
if($root->left == null && $root->right == null && $root->val == $sum){
//当该节点是叶子节点时,且节点的值=sum,即已找到结果路径,将路径path压入结果数组中
$res[] = $path;
}else{
//否则将继续进行递归
if($root->left != null){
$this->getAllPath($root->left,$sum - $num,$path,$res);
}
if($root->right != null){
$this->getAllPath($root->right,$sum - $num,$path,$res);
}
}
}
}
437.路径总和III
给定一个二叉树,它的每个结点都存放着一个整数值。
找出路径和等于给定数值的路径总数。
路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
示例:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8 10 / \ 5 -3 / \ \ 3 2 11 / \ \ 3 -2 1 返回 3。和等于 8 的路径有: 1. 5 -> 3 2. 5 -> 2 -> 1 3. -3 -> 11
与102区别:不要求从根节点到叶子节点,只要是连续的就行,只需返回结果数量
解法:从根节点开始,依次从每个节点遍历到根节点,求路径和是否=sum,取结果
class Solution {
function pathSum($root, $sum) {
if($root == null) return 0;//树为空,则返回0
$queue = [$root]; //利用队列,层次遍历,再进行递归
$times = 0; //记录路径数量
while(!empty($queue)){
$curNode = array_shift($queue); //取出当前节点
$times += $this->dfs($curNode,$sum); //递归:进行深度优先搜索
if($curNode->left) $queue[] = $curNode->left; //左子树不为空,将左子树入队
if($curNode->right) $queue[] = $curNode->right; //右子树不为空,将右子树入队
}
return $times;
}
public function dfs($node, $sum){
$res = 0;
if($node == null) return $res; //若节点为空,返回0
$num = $node->val;
if($num == $sum) $res = 1; //若节点的值=sum,则记录成功1条
//不到叶子节点还不能返回res,因为节点的值可能为负数,可能下方运算后,还可以得到结果
if($node->left == null && $node->right == null) return $res; //若该节点为叶子节点,则直接返回结果res次数
$res += $this->dfs($node->left,$sum-$num) + $this->dfs($node->right,$sum-$num); //左右孩子递归,sum取减节点的值后的值
return $res;
}
}
404.左叶子之和
计算给定二叉树的所有左叶子之和。
示例:
3 / \ 9 20 / \ 15 7 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
该题比较简单,只需要递归遍历取得左叶子节点,相加即可
class Solution {
function sumOfLeftLeaves($root) {
if($root == null) return 0; //当树为空时,返回0
if($root->left == null && $root->right == null) return 0; //当节点为叶子节点时,返回0,因为该节点可能是右节点
//左叶子节点在这条判断中取值:当该节点存在左节点,且该左节点为叶子结点时,则可取该左孩子的值进结果中
if($root->left && $root->left->left == null && $root->left->right == null){
return $root->left->val + $this->sumOfLeftLeaves($root->right); //取左孩子的子,并继续递归右子树
return $this->sumOfLeftLeaves($root->left) + $this->sumOfLeftLeaves($root->right); //递归左右子树
}
}
129. 求根到叶子节点数字之和
给定一个二叉树,它的每个结点都存放一个 0-9
的数字,每条从根到叶子节点的路径都代表一个数字。
例如,从根到叶子节点路径 1->2->3
代表数字 123
。
计算从根到叶子节点生成的所有数字之和。
说明: 叶子节点是指没有子节点的节点。
示例 1:
输入: [1,2,3] 1 / \ 2 3 输出: 25 解释:从根到叶子节点路径1->2代表数字12. 从根到叶子节点路径1->3代表数字13. 因此,数字总和 = 12 + 13 =25.示例 2:
输入: [4,9,0,5,1] 4 / \ 9 0 / \ 5 1 输出: 1026 解释:从根到叶子节点路径4->9->5代表数字 495. 从根到叶子节点路径4->9->1代表数字 491. 从根到叶子节点路径4->0代表数字 40.
解法:连接所有路径,并相加
class Solution {
/**
* @param TreeNode $root
* @return Integer
*/
private $sum = 0; //结果之和
function sumNumbers($root) {
if($root == null) return 0; //树为空,直接返回0
$this->findSum($root,''); //递归(节点,路径)
return $this->sum;
}
private function findSum($root,$path){
if($root == null) return null; //当节点为空,返回空
$path = $path.$root->val; //取当前路径,连接最新的值
if($root->left == null && $root->right == null){ //当该节点为叶子节点时,将结果sum加上路径对应的值
$this->sum = $this->sum + $path;
}
if($root->left) $this->findSum($root->left,$path); //没找到叶子节点则继续递归遍历左右子树
if($root->right) $this->findSum($root->right,$path);
return ;
}
}
257.二叉树的所有路径
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
输入: 1 / \ 2 3 \ 5 输出: ["1->2->5", "1->3"] 解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3
解法:遍历左右孩子,从叶子节点回溯路径到根节点,其间按题目要求进行链接
class Solution {
function binaryTreePaths($root) {
if($root == null) return []; //当节点为空,返回空数组
if($root->left == null && $root->right == null) return [(string)$root->val]; //该节点为叶子节点时,返回一个元素的数组
$res = []; //记录结果
//左右孩子分别递归遍历/
if($root->left != null){
$left = $this->binaryTreePaths($root->left); //左子树进行递归
$len = count($left);
for($i = 0;$i<$len;++$i){
$res[] = (string)$root->val . '->' . $left[$i]; //对取得的值按题目要求进行连接
}
}
if($root->right != null){
$right = $this->binaryTreePaths($root->right); //左子树进行递归
$len = count($right);
for($i = 0;$i<$len;++$i){
$res[] = (string)$root->val . '->' . $right[$i]; //对取得的值按题目要求进行连接
}
}
return $res;
}
}