LeetCode之路:404. Sum of Left Leaves
来源:互联网 发布:mac flamingo 编辑:程序博客网 时间:2024/05/29 18:03
一、引言
这是一道乍看比较简单,但是稍不注意做起来就会比较痛苦的题目 T_T ~~~
这道题我做了很久,一开始审错了题目,提交了之后看到了 Error Case 之后发现自己理解错了,再之后做出了第一个版本的代码,但是对于代码的简洁度不够满意,然后又拼命为了减少代码行数思考更加简洁的办法,于是又写出了好几个版本的代码~~~
废话不多说,让我们先看题吧:
Find the sum of all left leaves in a given binary tree.
Example:
题目信息很简练,还是翻译一下:
请计算给定二叉树中所有的独立的左叶子节点的和。
举例:
这里有两个独立的左叶子节点,分别是 9 和 15,于是返回 24 即可。
这里非常简单,需要理解的就是左叶子节点的含义:
- 此节点一定拥有父节点
- 此节点一定没有子节点
- 此节点一定是父节点的左子节点
也就是说,满足了上述三个条件的节点,才是我们寻找的节点。
那么,这道题该如何做呢?
二、抓住重点:一定是父节点的左子节点
这道题乍一看好像非常简单的样子,仿佛我随便一个递归遍历就可以出来了 : )
于是我就写出了第一个错误的答案~~~
其实在引言里已经分析的非常清楚了,这里需要遍历整个二叉树寻找满足这些条件的节点:
没有子节点的、并且是其父节点的左子节点的节点
让我们一个一个条件的看:
该节点一定要有父节点:这个简单,我们只需要判断 root 是否为空即可(因为整个二叉树只有 root 节点没有父节点)
该节点没有子节点:这个其实也简单,我们需要拿到该节点,查看该节点的 left 和 right 指针是否为空
该节点一定是父节点的左子节点:这一条件或许比较难,但是仔细想想其实也比较好实现;我们遍历整个二叉树,当拿到父节点时,我们对于左子节点进行左叶子节点的寻找工作,而对于右子节点,我们只需要递归遍历即可,不需要进行左叶子节点的寻找工作
根据上述的逻辑,我写出了第一份通过了 Test Case 的代码:
// my solution 1 , runtime = 6 msclass Solution1 {public: int sumOfLeftLeaves(TreeNode* root) { if (root == nullptr) return 0; if (root->left == nullptr && root->right == nullptr) return 0; if (root->left) { if (root->left->left == nullptr && root->left->right == nullptr) count += root->left->val; else sumOfLeftLeaves(root->left); } if (root->right) sumOfLeftLeaves(root->right); return count; }private: int count = 0;};
代码简单解释下:
首先,我对于 root 是否为空进行了判断,保证了“一定有父节点”这一条件
其次,我分成两个方向,其中右子节点的方向我们只需要递归遍历即可;左子节点有所不同,我们需要判断左子节点是否拥有子节点,如果没有的话,就意味着我们的左子节点为左叶子节点,那么我们就可以拿到这个节点的值进行计算
最后,我们按照第 2 步的逻辑遍历整个二叉树,最后得到所有左子节点的值的和返回即可
逻辑非常简单,但是代码写的我不满意,总想能不能再简化些。
于是我写了个只有 4 行的方法(使用了条件语句进行缩减):
// my solution 2 concise , runtime = 6 msclass Solution2 {public: int sumOfLeftLeaves(TreeNode* root) { if (!root || (!root->left && !root->right)) return 0; if (root->left) !root->left->left && !root->left->right ? count += root->left->val : sumOfLeftLeaves(root->left); if (root->right) sumOfLeftLeaves(root->right); return count; }private: int count = 0;};
可能觉得这里的 root 和 root->left 和 root->right 没必要单起一行进行判断,又缩减了下逻辑:
// my solution 3 concise , runtime = 3 msclass Solution4 {public: int sumOfLeftLeaves(TreeNode* root) { if (root && root->right) sumOfLeftLeaves(root->right); if (root && root->left) !root->left->left && !root->left->right ? count += root->left->val : sumOfLeftLeaves(root->left); return count; }private: int count = 0;};
但是,这其实已经违背了代码的可读性这个要求,不过说实话,当代码写成了条件语句的时候,我自己来说,能够更清晰地看到我进行了几次判断,尽管逻辑都是一样的。
不过说实话,条件语句如此的疯狂的嵌套缩减代码是得不偿失的,我也就是玩玩而已 ^_^ ~~~
三、不使用私有变量:利用函数的返回值计算 sum 值
可能你也注意到了,我前三个方法都是定义了一个类私有变量 count 来计算和值。
可不可以不使用这个私有变量呢?
答案是可以的。
直接上代码吧:
// perfect solution , runtime = 6 msclass Solution4 {public: int sumOfLeftLeaves(TreeNode* root) { if (root == nullptr) return 0; int count = 0; if (root->left != nullptr) { if (root->left->left == nullptr && root->left->right == nullptr) count += root->left->val; else count += sumOfLeftLeaves(root->left); } count += sumOfLeftLeaves(root->right); return count; }};
这段代码的思路跟前三个方法的差不多,只是内部定义了一个 count 值进行计算和返回而已。
我们要记住这么一句话:
递归与循环不同,我们在思考递归的时候,不能理解为循环,递归是一种顺序执行的方法,也就是说你写的这个函数,当执行到了哪里,那么这行代码之前的所有逻辑都已经处理完成了
也就是说,看到这里的代码,当我们的代码执行到了 :
if (root->left != nullptr) { if (root->left->left == nullptr && root->left->right == nullptr) count += root->left->val; else count += sumOfLeftLeaves(root->left);}
我们就应该理解为,当前程序已经将当前的 root 节点的左子树 root->left 上的所有的左叶子节点的值计算完毕了。
当我们的代码执行到了 :
count += sumOfLeftLeaves(root->right);
的时候,我们的程序就已经将当前节点 root 的右子树 root->right 上的所有的左叶子节点的值计算完毕。
因此最后的:
return count;
就是我们所需要的所有的左叶子节点的和。
那么我们的探索也就到此为止了。
那么这道题只有这么一个思路吗?
在我查看了多个高票答案后,我很遗憾的发现可能还真是这样。很多方法都是写着不同的标题,但是其内涵都是一样的。
哈哈,不管怎么样,我们也算是通过自己的努力完成了这道题了吗不是?
四、总结
这道题我做了比较久,可能太想想出一个更简单的方法,可能是因为本身就只有这么一个方法了吧,所以更简单的方法可能很难找到。
不过递归仍然是一个非常有用的工具,尤其是在对待二叉树的问题上。
端午节就要到了,想想假期要干点什么呢?做做题,写写代码,写写博客,看看书,玩玩游戏什么的。
人生啊,就是这么美好 ^_^~~~
- LeetCode之路:404. Sum of Left Leaves
- LeetCode之Sum of Left Leaves
- LeetCode笔记:404. Sum of Left Leaves
- 【leetcode】404. Sum of Left Leaves【E】
- LeetCode—404. Sum of Left Leaves
- [LeetCode]404. Sum of Left Leaves
- Leetcode 404. Sum of Left Leaves
- LeetCode 404. Sum of Left Leaves
- 404. Sum of Left Leaves - leetcode
- [LeetCode]--404. Sum of Left Leaves
- LeetCode 404. Sum of Left Leaves
- [leetcode]404. Sum of Left Leaves
- LeetCode-404. Sum of Left Leaves
- LeetCode 404. Sum of Left Leaves
- LeetCode 404. Sum of Left Leaves
- leetcode 404. Sum of Left Leaves
- leetcode(88).404. Sum of Left Leaves
- 【LeetCode】 404. Sum of Left Leaves
- Storm Kafka + Storm + HBase实例
- c++成员变量的初始化顺序
- 算法题目-删除链表中重复的结点
- 《UNIX网络编程 卷1》 笔记: 基本UDP套接字编程
- 半平面交 模板 bzoj2618 【Cqoi2006】凸多边形
- LeetCode之路:404. Sum of Left Leaves
- Java 8 – 将 Stream 转换为 List
- HTML5之画布(canvas)(一)
- Kotlin笔记(一)——Hello Kotlin
- opencv中waitkey(0)的使用
- 1178: “顺”序列
- IDEA 导入java web项目后的相关配置
- Log4j的使用方法
- size_type,size_t和ptrdiff_t