前不久阿里内推之后做了阿里的笔试题,半个小时里完全无从下手,最后虽然想出了思路,但时间已到无力回天,只能对着那0%的通过率望洋兴叹,可怜一颗努力刷题的真心。今天看到有同学也准备做阿里的笔试,于是也来凑凑热闹,所幸还是写出了代码,算是弥补了之前的遗憾。分享在此,期待各位讨论研习。(以下内容仅凭记忆,如有偏差,对解题也是没有太大影响的)
1. 问题描述
给定一组输入,每行为一个三位数,输入0或者空行表示结束。这一组输入对应一个二叉树,每一行的三位数对应二叉树中的一个节点,对应规则为:百位表示该节点在二叉树中的层数,十位表示该节点在二叉树该层中的第几个节点,个位数表示该节点的值。限定二叉树的层数最大为4,且每行的三位数递增输入。
求所有叶子节点到根节点的路径所经过节点值的总和。
1.1样例输入
113
211
215
0
1.2样例输出
12
1.3样例解释
根据输入还原二叉树为:
3
/ \
1 5
叶子节点到根节点有两条路径:1->3和5->3,求和得到:(1+3)+(5+3)=12
2. 思路分析
在所有叶子节点到根节点的路径中,叶子节点只经过一次,非叶子节点的经过次数为其子节点经过次数之和。
3. 编程实现
在如下的代码中,counts数组用于记录每个节点被经过次数,之所以将其大小设置为31,是为了将叶子节点的下一层也补全为完全二叉树,因为是补全的节点,所以经过次数为0,叶子节点的判定就变成:若子节点经过次数之和为0则为叶子节点,置该叶子节点经过次数为1。
import java.util.Objects;
import java.util.Scanner;
/**
* Created by steel on 2017/3/15.
*/
public class Main {
public static void main(String[] args){
int[] counts=new int[31]; //记录每个节点被经过的次数
for(int i=0;i<31;i++) counts[i]=0;
int[] vector = new int[15]; //最多四层,所以节点不超过15个
Scanner s = new Scanner(System.in);
int size=0;
for(;size<15;size++){
String str = s.next();
if(str==null || Objects.equals(str, "") || Objects.equals(str, "0")) break;
vector[size] = Integer.parseInt(str.trim());
}
for(int i=size-1;i>=0;i--){
int index = (vector[i]%100)/10;
int floor = vector[i]/100;
int cntIndex = (int)Math.pow(2,floor-1)+index;//节点在完全二叉树中的下标
if(counts[cntIndex*2]+counts[cntIndex*2-1]==0)counts[cntIndex]=1;//如果是叶子节点,经过次数为1
else counts[cntIndex] =counts[cntIndex*2]+counts[cntIndex*2-1];//非叶子节点经过次数为其子节点经过次数之和
}
int sum=0;
for(int i=0;i<size;i++){
int value = vector[i]%10;
int index = (vector[i]%100)/10;
int floor = vector[i]/100;
int cntIndex = (int)Math.pow(2,floor-1)+index;
sum+=value*counts[cntIndex];//求和
}
System.out.println(sum);
}
}