题目:
输入一颗二叉树,你的任务是按照从上到下、从左到右的顺序输出各个节点的值。每个节点都按照从根节点到他的移动序列给出(L表示左,R表示右)。
在输入中,每个节点的左括号和右括号之间没有空格,相邻节点之间用一个空格隔开。每棵树的输入用一对空括号()结束,空括号不代表一个节点。如图:
注意:如果从根节点到某个叶子节点的路径上有的节点没有在任何输入中给出,或者给出了超过一次,应当输出-1,节点个数不超过256。
样例输入:
(11,LL)(7,LLL)(8,R)(5,)(4,L)(13,RL)(2,LLR)(1,RRR)(4,RR)()
(3,L)(4,R)()
样例输出:
5 4 8 11 13 4 7 2 1
-1
在这里给出Java的解决方法,用到了二叉树数据结构特点:二叉树中一个节点k的左子节点是2k,右子节点是2k+1。
思路:
遍历逗号右边的方向字符串,根据二叉树一个节点的左子节点是2K,右子节点
是2K+1的特点,计算出最终这个节点的编号。
例如: LL是1*2*2;
LLL是1*2*2*2;
R是1*2+1;
LLR是1*2*2*2+1.
然后再把逗号前面的数字填入刚计算出的节点里。
把每个节点填入集合中,遍历集合,对于每一个不是0的节点,判断其有没有父节点,
如果没有父节点,则打印-1。
public class Test10 { private static final int MAXN = 20; private static int[] s = new int[1<<MAXN]; public static void main(String[] args) { Scanner scan = new Scanner(System.in); String s = scan.nextLine(); s = s.substring(1, s.length()-3); //System.out.println(s); String[] ss = s.split("\\)\\("); String result = getResult(ss); System.out.println(result); } public static String getResult(String[] ss) { for(int i=0;i<ss.length;i++) { String[] pos = ss[i].split(","); if(pos.length == 1) { s[0] = Integer.parseInt(pos[0]);//如果长度是1,则说明是根节点 continue; } int p = 1; for(int j=0;j<pos[1].length();j++) { //按照方向遍历,根据左子节点是2k,右子节点是2k+1的特点计算 if(pos[1].charAt(j) == ‘L‘) { p *= 2; } else if(pos[1].charAt(j) == ‘R‘) { p = p*2 + 1; } } //计算出来的p是角标,将pos[0]填充到对应的角标上 s[p-1] = Integer.parseInt(pos[0]);//计算出来会多出一个,需要-1 } //检查是否是一颗正确的二叉树 boolean flag = check(s); if(flag) { String result = ""; for(int i=0;i<s.length;i++) { if(s[i] != 0) { result += s[i] + " "; } } return result; } return "-1"; } private static boolean check(int[] s) { /* * 从s数组角标为1的地方开始检查,检查每个节点的父节点是否是0,如果都不是0,则说明是一颗正确的树, * 如果有某个是0,则说明错误,是0说明这个节点的父节点不存在,按照需求来说,定义为错误。 */ for(int i=1;i<s.length;i++) { if(s[i] != 0) { if(i%2 == 1) { int temp = i / 2; if(s[temp] == 0) { return false; } } else { int temp = (i-1) / 2; if(s[temp] == 0) { return false; } } } } return true; } }