算法练习 DAY17 || 110. 平衡二叉树 257. 二叉树的所有路径 404. 左叶子之和

110. 平衡二叉树

本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1

这里强调一波概念:

二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数。
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。

但leetcode中强调的深度和高度很明显是按照节点来计算的,如图:
在这里插入图片描述
求深度可以从上到下去查 所以需要前序遍历(中左右),而高度只能从下到上去查,所以只能后序遍历(左右中)
本题求高度,所以采用后序

思路:
递归三步曲分析:

明确递归函数的参数和返回值

参数:当前传入节点。
返回值:以当前传入节点为根节点的树的高度。

那么如何标记左右子树是否差值大于1呢?

如果当前传入节点为根节点的二叉树已经不是二叉平衡树了,还返回高度的话就没有意义了。

所以如果已经不是二叉平衡树了,可以返回-1 来标记已经不符合平衡树的规则了。
在这里插入图片描述

class Solution {
public:
	/*
		递归三要素
		1、确定形参和返回值
		形参:当前节点
		返回:当前节点的高度 
		(跟递归后序求最大深度的思路是一样的)
		2、明确终止条件
		碰到空节点 返回的高度就是0
		3、单层遍历条件
		比较当前节点左右子树的高度 大于一就返回-1
		小于等于1就返回这个节点的高度
	*/
	int getHeight(TreeNode* node) {
		if (node == nullptr) return 0;
		int leftH = getHeight(node->left);
		if (leftH == -1) return -1;
		int rightH = getHeight(node->right);
		if (rightH == -1) return -1;
		return abs(leftH - rightH) > 1 ? -1 : max(leftH , rightH) + 1;
	}
	bool isBalanced(TreeNode* root) {
		return getHeight(root) == -1 ? false : true;
		
	}
};

257. 二叉树的所有路径

给定一个二叉树,返回所有从根节点到叶子节点的路径。

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

思路:
这道题目要求从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。

在这道题目中将第一次涉及到回溯,因为我们要把路径记录下来,需要回溯来回退一一个路径在进入另一个路径。

前序遍历以及回溯的过程如图:
在这里插入图片描述
在这里插入图片描述

class Solution {
public:
	//递归
	/*
		1、要通过中节点去找左右孩子,用前序遍历更方便
		2、递归的终止条件:
		   这里是要找路径,找到一个就pushback一个
		   所以找到叶子节点就可以了。
		   判断叶子节点就是 cur!=null 但是左右为空
		3、递归的返回值和形参
		   形参:1、当前节点 2、存放不同路径的容器result  3、记录当前节点的容器 path
		   无需返回值 result和path在传入的时候都以引用传入即可
		4、单层逻辑
			当前的节点加进path
			遍历到叶子节点就把path放进reslut 说明拿到一条路径。同时pop 进行回溯
			否则就继续遍历
	
	*/
	void traversal(TreeNode* node,vector<int>& path,vector<string>& result) {
		path.push_back(node->val); //要先把遍历到的节点放进path
		//上面就是在处理中
		//写终止条件
		if (node != nullptr&&node->left == nullptr&&node->right == nullptr) {
			//把path里面的数据转成一条string放进result里面
			string s;
			for (int i = 0; i < path.size()-1; i++) {
				s += to_string(path[i]);
				s += "->";
			}
			s += to_string(path[path.size() - 1]);
			result.push_back(s);
			return;
		}
		//单层逻辑
		if (node->left) {
			traversal(node->left, path, result);
			path.pop_back(); //回溯
		}
		if (node->right) {
			traversal(node->right, path, result);
			path.pop_back();
		}

	}
	vector<string> binaryTreePaths(TreeNode* root) {
		vector<string> result;
		vector<int> path;
		if (root == nullptr) {
			return result;
		}
		traversal(root, path, result);
		return result;
	}
};

404. 左叶子之和

给定二叉树的根节点 root ,返回所有左叶子之和
在这里插入图片描述

节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点

class Solution {
public:
	/*
	递归参数:当前节点 返回值就是左叶子的值
	终止条件:当碰到空节点 返回0 
			  碰到叶子节点(做中节点),其左孩子一定为空,所以也返回0
	单层逻辑 :要通过父节点来判断是不是左叶子 是的话就返回
			   不是的话就继续便利
	*/
	int sumOfLeftLeaves(TreeNode* root) {
		//终止条件
		if (root == nullptr) return 0;
		if (root->left == nullptr && root->right == nullptr) return 0;

		int leftnum = sumOfLeftLeaves(root->left); //一路向左 找左叶子 找到以后会返回零
		if (root->left != nullptr && root->left->left== nullptr && root->left->right == nullptr) { //return回来以后 通过父节点找到做叶子的值
			leftnum = root->left->val;
		}

		//然后看当前父节点的右孩子有没有左叶子
		int rightnum = sumOfLeftLeaves(root->right);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值