【20200919 每日一题】刷题使我快乐。更多LeetCode答案请见我的GitHub zhangyixing1007/leetcode。
今天三个题解已上传至此文件夹。
进入正文。先看题目。
404. 左叶子之和
难度简单
计算给定二叉树的所有左叶子之和。 示例:
3
/
9 20
/
15 7
在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
解法一 单纯dfs递归
最直观的想法,当然是递归进行dfs啦,然后考察每一棵左子树是不是一个左叶子节点。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
dfs(root);
return ans;
}
int ans=0;
void dfs(TreeNode root){
if(root==null) return;
if(root.left!=null){
if(root.left.left==null&&root.left.right==null) ans+=root.left.val;
else dfs(root.left);
}
dfs(root.right);
}
}
为什么是考虑当前节点的左子树,而不是考虑当前节点呢?
因为当我们拿到一个节点的时候,我们无法知道这个节点是父节点的左子树还是右子树--想要明确这一点,那么函数要多一个变量来表明该节点的左右。
解法二 dfs递归+标志位
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
dfs(root, false);
return ans;
}
int ans=0;
void dfs(TreeNode root, boolean isLeftNode){
if(root==null) return;
if(isLeftNode && root.left==null && root.right==null){
ans+=root.val;
}else{
dfs(root.left, true);
dfs(root.right, false);
}
}
}
解法三 迭代+Pair
dfs可以,那么bfs可不可以呢?
当然可以啦,只是需要多一个变量来记录每一个节点是否为左节点。这里我们就要用到Pair这个数据结构了。
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root==null) return 0;
Queue<Pair<TreeNode, Boolean>> q=new LinkedList<>();
q.add(new Pair(root,false));
int ans=0;
while(!q.isEmpty()){
Pair<TreeNode, Boolean> curr=q.poll();
TreeNode key=curr.getKey();
Boolean value=curr.getValue();
if(value && key.left==null && key.right==null){
ans+=key.val;
}else{
if(key.left!=null) q.add(new Pair(key.left,true));
if(key.right!=null) q.add(new Pair(key.right,false));
}
}
return ans;
}
}
这种做法用来锻炼一下大脑就好。因为实际上,还是很慢的。(多半是因为Queue频繁出队入队的缘故。)
解法三中既然提到了Pair,我就来扒一下Pair的常见用法吧。(javafx.util.Pair)
参考 https://docs.oracle.com/javase/8/javafx/api/javafx/util/Pair.html
Pair<K,V> p=new Pair<>(K key, V value);
//新建一个键为K类型,值为V类型的Pair
K key=p.getKey(); //获得键
V value=p.getValue(); //获得值
//还有一些常见的
p.equals(Pair pp)//当且仅当键和值都相等时才相等
p.hashCode()//与键和值都有关
p.toString()//写出来类似 “键=值”的形式
Pair所属的javafx.util包在jdk 1.8的类库里面有,但在OpenJDK 8里面是没有的。参考 一场因OpenJDK引发的血案 - 清香白莲的文章 - 知乎 https://zhuanlan.zhihu.com/p/103765203。
贴一下javafx.util.Pair的源码(精简版,删掉部分注释)
package javafx.util;
import java.io.Serializable;
import javafx.beans.NamedArg;
public class Pair<K,V> implements Serializable{
private K key;
public K getKey() { return key; }
private V value;
public V getValue() { return value; }
public Pair(@NamedArg("key") K key, @NamedArg("value") V value) {
this.key = key;
this.value = value;
}
@Override
public String toString() {
return key + "=" + value;
}
@Override
public int hashCode() {
return key.hashCode() * 13 + (value == null ? 0 : value.hashCode());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof Pair) {
Pair pair = (Pair) o;
if (key != null ? !key.equals(pair.key) : pair.key != null) return false;
if (value != null ? !value.equals(pair.value) : pair.value != null) return false;
return true;
}
return false;
}
}
除了这个Pair,还有一个位于不同位置的Pair (org.apache.commons.lang3.tuple.Pair),接口差不多,但是实现方式有些不同。具体见 http://www.coderead.cn/lib/org.apache.commons/commons-lang3/3.5/org/apache/commons/lang3/tuple/Pair.java。