2018届实习-阿里巴巴内推编程题

对于一个由一位十进制整数构成的二叉树,如果深度不超过4,可以用一个三位十进制整数构成的数组表示,具体规则如下:

1、百位数表示树的层次L,1<=L<=4;十位数表示在该层次中的位置P,1<=P<=8;个位数表示数值V。

2、数组里,L一定是单增的,也就是说后一个数的L大于等于前一个数的L;

3、对于同一个L,P也是单增的,就是说在L不变的情况下,后一个数的P大于等于前一个数的P。

例如:[ 113, 215, 221 ]

   3
  / \
 5   1

现在要求这个树所有到叶子节点的路径和,对于例子中,路径和为 (3+5)+(3+1)=12

题目的意思就是给出了几个三位数,比如 113 ,代表的是深度为1 ,左边第1个的数值 为 3 ; 215表示深度为2,左边第1个的数值为5 。。。。。。

样例:
1
/ \
2 3
/ \
4 5
输入:
111
212
223
314
325
输出:
19

解题思路是:

1.读取输入的内容,将三位数拆分,分别用数组bai,数组shi,数组ge存储对应位上的值

2.用数组treeArray构建二叉树,保存ge数组的值

3.遍历数组treeArray,找出所有叶子结点,然后根据叶子节点求出根节点到该叶子结点的路径长度

代码如下:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        // 读取输入的内容
        List<Integer> input = new ArrayList<Integer>();
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        while(str != null && !str.isEmpty()){
            Integer value = Integer.parseInt(str);
            if(value==0)
                break;
            input.add(value);
            str = sc.nextLine();
        }
        int[] A = new int[input.size()];
        for (int i = 0; i < A.length; i++) {
            A[i] = input.get(i).intValue();
        }
        int res = resolve(A);
        System.out.println(res);
    }
    static int resolve(int[] A){
        // 将三位数拆分,分别用数组bai,数组shi,数组ge存储对应位上的值
        int len = A.length;
        int[] bai = new int[len];
        int[] shi = new int[len];
        int[] ge = new int[len];
        for (int i = 0; i < len; i++) {
            bai[i] = A[i]/100;
            shi[i] = A[i]%100/10;
            ge[i] = A[i]%10;
        }
        final int P = 15;
        int[] treeArray = new int[P];
        for (int i = 0; i < treeArray.length; i++) {
            treeArray[i] = Integer.MIN_VALUE;
        }
        // 用数组treeArray构建二叉树,保存ge数组的值
        for(int i = 0 ; i < len;i++){
            int loc = bai[i]*(bai[i]-1)/2+shi[i]-1;
            treeArray[loc] = ge[i];
        }
        // 遍历数组treeArray,找出所有叶子结点
        int sum = 0;
        for (int i = 0; i < P; i++) {
            if(treeArray[i] != Integer.MIN_VALUE){
                if(i*2+1 >= P || i*2+2>=P){
                    //是叶子结点
                    sum+=helper(treeArray,i);
                }
                if(treeArray[i*2+1] == Integer.MIN_VALUE){
                    // 是叶子节点
                    sum+=helper(treeArray,i);
                }
            }
        }
        return sum;
    }
    // 根据叶子节点求出根节点到该叶子结点的路径长度
    static int helper(int[] treeArray,int index){
        // 是根节点
        if(index == 0){
            return treeArray[index];
        }
        if(index %2==1){
            // 是左节点
            return treeArray[index]+helper(treeArray,(index-1)/2);
        }else{
            // 是右节点
            return treeArray[index]+helper(treeArray,(index-2)/2);
        }
    }
}

关于判断是否是叶子结点的代码:

if(treeArray[i] != Integer.MIN_VALUE){
    if(i*2+1 >= P || i*2+2>=P){
        //是叶子结点
        sum+=helper(treeArray,i);
    }
    if(treeArray[i*2+1] == Integer.MIN_VALUE){
        // 是叶子节点
        sum+=helper(treeArray,i);
    }
}

第一个if的意思是:如果当前位置的索引为i,
那么左子节点的索引为i*2+1,右子节点的索引为i*2+2
如果左子节点和右子节点的索引超过treeArray的长度,表明当前索引i在最后一行,则一定是叶子结点

第二个if的意思是:如果满足了第一个if,也就是说当前的索引i不在最后一行,如果它的左子节点为空,那么一定是叶子节点

测试

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_16403141/article/details/79473815