递归和迭代_LeetCode 0404 左叶子之和,递归&迭代,Pair的常用方法

【20200919 每日一题】刷题使我快乐。更多LeetCode答案请见我的GitHub zhangyixing1007/leetcode。

今天三个题解已上传至此文件夹。

76d0f83060cf3f9e427dac95a624a30c.png

进入正文。先看题目。

404. 左叶子之和
难度简单
计算给定二叉树的所有左叶子之和。 示例:
3
/
9 20
/
15 7
在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24

解法一 单纯dfs递归

最直观的想法,当然是递归进行dfs啦,然后考察每一棵左子树是不是一个左叶子节点。

1d79b6b2499da9331c38911a9630eb0d.png
/**
 * 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递归+标志位

c0d5fc58ef697dc00ca5a3494f691e3c.png
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这个数据结构了。

63abd4a17bbd91d038fdd4eb0c19a947.png
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。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值