做了这么多题目了,会求左叶子之和么?

开发 前端
平时我们解二叉树的题目时,已经习惯了通过节点的左右孩子判断本节点的属性,而本题我们要通过节点的父节点判断本节点的属性。

[[416239]]

本文转载自微信公众号「代码随想录」,作者程序员Carl 。转载本文请联系代码随想录公众号。

左叶子之和

题目地址:https://leetcode-cn.com/problems/sum-of-left-leaves/

计算给定二叉树的所有左叶子之和。

示例:

思路

首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。

因为题目中其实没有说清楚左叶子究竟是什么节点,那么我来给出左叶子的明确定义:如果左节点不为空,且左节点没有左右孩子,那么这个节点就是左叶子

大家思考一下如下图中二叉树,左叶子之和究竟是多少?

其实是0,因为这棵树根本没有左叶子!

那么判断当前节点是不是左叶子是无法判断的,必须要通过节点的父节点来判断其左孩子是不是左叶子。

如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子,判断代码如下:

  1. if (node->left != NULL && node->left->left == NULL && node->left->right == NULL) { 
  2.     左叶子节点处理逻辑 

递归法

递归的遍历顺序为后序遍历(左右中),是因为要通过递归函数的返回值来累加求取左叶子数值之和。。

递归三部曲:

1.确定递归函数的参数和返回值

判断一个树的左叶子节点之和,那么一定要传入树的根节点,递归函数的返回值为数值之和,所以为int

使用题目中给出的函数就可以了。

2.确定终止条件

依然是

  1. if (root == NULLreturn 0; 

3.确定单层递归的逻辑

当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和 右子树左叶子之和,相加便是整个树的左叶子之和。

代码如下:

  1. int leftValue = sumOfLeftLeaves(root->left);    // 左 
  2. int rightValue = sumOfLeftLeaves(root->right);  // 右 
  3.                                                 // 中 
  4. int midValue = 0; 
  5. if (root->left && !root->left->left && !root->left->right) { 
  6.     midValue = root->left->val; 
  7. int sum = midValue + leftValue + rightValue; 
  8. return sum

整体递归代码如下:

  1. class Solution { 
  2. public
  3.     int sumOfLeftLeaves(TreeNode* root) { 
  4.         if (root == NULLreturn 0; 
  5.  
  6.         int leftValue = sumOfLeftLeaves(root->left);    // 左 
  7.         int rightValue = sumOfLeftLeaves(root->right);  // 右 
  8.                                                         // 中 
  9.         int midValue = 0; 
  10.         if (root->left && !root->left->left && !root->left->right) { // 中 
  11.             midValue = root->left->val; 
  12.         } 
  13.         int sum = midValue + leftValue + rightValue; 
  14.         return sum
  15.     } 
  16. }; 

以上代码精简之后如下:

  1. class Solution { 
  2. public
  3.     int sumOfLeftLeaves(TreeNode* root) { 
  4.         if (root == NULLreturn 0; 
  5.         int midValue = 0; 
  6.         if (root->left != NULL && root->left->left == NULL && root->left->right == NULL) { 
  7.             midValue = root->left->val; 
  8.         } 
  9.         return midValue + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right); 
  10.     } 
  11. }; 

迭代法

本题迭代法使用前中后序都是可以的,只要把左叶子节点统计出来,就可以了,那么参考文章 二叉树:听说递归能做的,栈也能做!和二叉树:迭代法统一写法中的写法,可以写出一个前序遍历的迭代法。

判断条件都是一样的,代码如下:

  1. class Solution { 
  2. public
  3.     int sumOfLeftLeaves(TreeNode* root) { 
  4.         stack<TreeNode*> st; 
  5.         if (root == NULLreturn 0; 
  6.         st.push(root); 
  7.         int result = 0; 
  8.         while (!st.empty()) { 
  9.             TreeNode* node = st.top(); 
  10.             st.pop(); 
  11.             if (node->left != NULL && node->left->left == NULL && node->left->right == NULL) { 
  12.                 result += node->left->val; 
  13.             } 
  14.             if (node->right) st.push(node->right); 
  15.             if (node->left) st.push(node->left); 
  16.         } 
  17.         return result; 
  18.     } 
  19. }; 

总结

这道题目要求左叶子之和,其实是比较绕的,因为不能判断本节点是不是左叶子节点。

此时就要通过节点的父节点来判断其左孩子是不是左叶子了。

平时我们解二叉树的题目时,已经习惯了通过节点的左右孩子判断本节点的属性,而本题我们要通过节点的父节点判断本节点的属性。

希望通过这道题目,可以扩展大家对二叉树的解题思路。

其他语言版本

Java

递归

  1. class Solution { 
  2.     public int sumOfLeftLeaves(TreeNode root) { 
  3.         if (root == nullreturn 0; 
  4.         int leftValue = sumOfLeftLeaves(root.left);    // 左 
  5.         int rightValue = sumOfLeftLeaves(root.right);  // 右 
  6.                                                         
  7.         int midValue = 0; 
  8.         if (root.left != null && root.left.left == null && root.left.right == null) { // 中 
  9.             midValue = root.left.val; 
  10.         } 
  11.         int sum = midValue + leftValue + rightValue; 
  12.         return sum
  13.     } 

迭代

  1. class Solution { 
  2.     public int sumOfLeftLeaves(TreeNode root) { 
  3.         if (root == nullreturn 0; 
  4.         Stack<TreeNode> stack = new Stack<> (); 
  5.         stack.add(root); 
  6.         int result = 0; 
  7.         while (!stack.isEmpty()) { 
  8.             TreeNode node = stack.pop(); 
  9.             if (node.left != null && node.left.left == null && node.left.right == null) { 
  10.                 result += node.left.val; 
  11.             } 
  12.             if (node.right != null) stack.add(node.right); 
  13.             if (node.left != null) stack.add(node.left); 
  14.         } 
  15.         return result; 
  16.     } 

Python

递归

  1. class Solution: 
  2.     def sumOfLeftLeaves(self, root: TreeNode) -> int
  3.         if not root:  
  4.             return 0 
  5.          
  6.         left_left_leaves_sum = self.sumOfLeftLeaves(root.left)  # 左 
  7.         right_left_leaves_sum = self.sumOfLeftLeaves(root.right) # 右 
  8.          
  9.         cur_left_leaf_val = 0 
  10.         if root.left and not root.left.left and not root.left.right:  
  11.             cur_left_leaf_val = root.left.val  # 中 
  12.              
  13.         return cur_left_leaf_val + left_left_leaves_sum + right_left_leaves_sum 

迭代

  1. class Solution: 
  2.     def sumOfLeftLeaves(self, root: TreeNode) -> int
  3.         ""
  4.         Idea: Each time check current node's left node.  
  5.               If current node don't have one, skip it.  
  6.         ""
  7.         stack = [] 
  8.         if root:  
  9.             stack.append(root) 
  10.         res = 0 
  11.          
  12.         while stack:  
  13.             # 每次都把当前节点的左节点加进去.  
  14.             cur_node = stack.pop() 
  15.             if cur_node.left and not cur_node.left.left and not cur_node.left.right:  
  16.                 res += cur_node.left.val 
  17.                  
  18.             if cur_node.left:  
  19.                 stack.append(cur_node.left
  20.             if cur_node.right:  
  21.                 stack.append(cur_node.right
  22.                  
  23.         return res 

 

责任编辑:武晓燕 来源: 代码随想录
相关推荐

2021-03-24 08:44:11

代码内存消耗语言

2021-06-09 10:10:20

代码内存编程语言

2021-06-14 07:23:42

Windows10操作系统微软

2018-05-09 11:04:35

Java程序员大数据

2020-12-31 05:49:44

FlinkSQL函数

2024-04-02 08:41:10

ArrayListSubList场景

2017-08-11 14:21:33

软件开发前端框架

2023-07-17 08:21:52

漏洞版本项目

2020-12-14 07:31:57

JDKJVM监控

2023-11-13 08:49:54

2018-06-26 15:00:24

Docker安全风险

2024-02-20 08:09:51

Java 8DateUtilsDate工具类

2018-03-05 10:40:21

安卓APPGoogle

2023-07-07 19:23:08

微软文字Claude

2022-01-12 20:04:09

网络故障断网事件网络安全

2017-12-21 19:38:50

润乾中间表

2021-01-14 05:08:44

编译链接

2022-07-26 23:43:29

编程语言开发Java

2021-01-29 08:52:10

App微信移动应用

2020-04-07 19:16:31

微信隐藏功能移动应用
点赞
收藏

51CTO技术栈公众号