二叉树遍历应用

测试工程师正在测试某款新型扫地机器人。工程师设计了一个形如二叉树(根节点记为root)的测试路径,扫地机器人自路径对应的根节点出发,一直行进至路径尽头(即二叉树叶节点)。如果这个路口的左右子节点都非空,机器人选择左转或右转的概率相等;如果这个路口的左右子节点仅一侧非空,则机器人选择非空侧走。工程师给每个路口标记了数字,并且仅在标记数字target的所有路口设置了监控摄像机。请问扫地机器人被监控至少拍到一次的概率是多少?1 <= 树的节点数 <= 10000。

输入:root = [1, 2, 3, 2, 5, 6, 2], target = 2
输出:0.75
解释:数组按二叉树层次遍历的顺序记录了标记数字。从1出发,从左侧走到2的概率为0.5(被拍到),从右侧走到3的概率为0.5,从3继续出发走到2的概率为0.5(被拍到),所以结果为0.5 + 0.5 * 0.5 = 0.75。
即:左侧分支被拍到的概率为0.5(圆圈的2是0.5,继续走到2或5,不会增加被拍概率,也不会降低被拍概率),右侧分支被拍到的概率为0.25(圆圈的2),合计为0.75。

输入:root = [1, null, 3, 2, 2], target = 2
输出:1
 
解答:
构造二叉树然后递归统计概率
private class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
        this.val = val;
    }
}

public float calProbability(Integer[] tree, int target) {
    if (tree.length == 0) {
        return 0;
    }
    //先构造树
    TreeNode root = new TreeNode(tree[0]);
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);
    int index = 1;
    while (!queue.isEmpty() && index < tree.length) {
        int size = queue.size();
        for (int i = index; i < index + 2 * size; i++) {
            TreeNode node = queue.poll();
            int left = i;
            int right = i + 1;
            if (null != tree[left]) {
                node.left = new TreeNode(tree[left]);
                queue.offer(node.left);
            } else {
                node.left = null;
            }

            if (null != tree[right]) {
                node.right = new TreeNode(tree[right]);
                queue.offer(node.right);
            } else {
                node.right = null;
            }
            i++;
        }
        index = index + 2 * size;
    }

    return getProbability(root, 1, target);
}

private float getProbability(TreeNode root, float f, int target) {
    if (target == root.val) {
        return f;
    } else if (root.left != null && root.right != null) {
        return getProbability(root.left, f / 2, target) + getProbability(root.right, f / 2, target);
    } else if (root.left != null) {
        return getProbability(root.left, f, target);
    } else if (root.right != null) {
        return getProbability(root.right, f, target);
    } else {
        return 0;
    }
}

 

解法二:

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
    // 以上为Leetcode二叉树节点定义,下述语句则用于本地构造二叉树用例
    public TreeNode left(int val) {
        this.left = new TreeNode(val); return this;
    }
    public TreeNode right(int val) {
        this.right = new TreeNode(val); return this;
    }
    public TreeNode left() {
        return this.left;
    }
    public TreeNode right() {
        return this.right;
    }
    // 以下语句将构造一棵层次顺序为[1, 2, 3, 2, 5, 6, 2]的满二叉树
    // TreeNode root = trust.new TreeNode(1); root.left(2).right(3);
    // root.left().left(2).right(5); root.right().left(6).right(2);
}
private double helper(TreeNode node, int target, double probability) { // 不保证正确性,因为递归很难分析-_-
    if (node == null) {
        return 0;
    }
    if (node.val == target) {
        return probability;
    }
    double leftProb = 0.0, rightProb = 0.0;
    if (node.left != null) {
        leftProb = (node.right != null) ? 0.5 : 1;
    }
    if (node.right != null) {
        rightProb = (node.left != null) ? 0.5 : 1;
    }
    return probability * (helper(node.left, target, leftProb) + helper(node.right, target, rightProb));
}
public double captureProbability(TreeNode root, int target) {
    return helper(root, target, 1.0);
}

测试用例如下:

TreeNode root = trust.new TreeNode(1); root.left(2).right(3);
root.left().left(2).right(5); root.right().left(6).right(2);
System.out.println(trust.captureProbability(root, 2)); //0.75
root = trust.new TreeNode(1); root.right(3); root.right().left(2).right(2);
System.out.println(trust.captureProbability(root, 2)); //1.0
root = trust.new TreeNode(1); root.right(3); root.right().left(3).right(4);
System.out.println(trust.captureProbability(root, 2)); //0.0

 

posted @ 2020-03-16 20:42  ren_zhg1992  阅读(643)  评论(0)    收藏  举报