7-4 列出叶结点
分数 300
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
对于给定的二叉树,本题要求你按从上到下、从左到右的顺序输出其所有叶结点。
输入格式:
首先第一行给出一个正整数 N(≤10),为树中结点总数。树中的结点从 0 到 N−1 编号。随后 N 行,每行给出一个对应结点左右孩子的编号。如果某个孩子不存在,则在对应位置给出 "-"。编号间以 1 个空格分隔。
输出格式:
在一行中按规定顺序输出叶结点的编号。编号间以 1 个空格分隔,行首尾不得有多余空格。
输入样例:
8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6
输出样例:
4 1 5
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
这是我一开始的代码,思路之后再讲解:
import java.util.*;
class NewNode {
int val = -1;
int look = 0;
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
NewNode left;
public NewNode getLeft() {
return left;
}
public void setLeft(NewNode left) {
this.left = left;
}
NewNode right;
public NewNode getRight() {
return right;
}
public void setRight(NewNode right) {
this.right = right;
}
NewNode parent;
public NewNode getParent() {
return parent;
}
public void setParent(NewNode parent) {
this.parent = parent;
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
ArrayList<NewNode> node = new ArrayList<>();
if(N > 10){
N = 10;
}
for (int i = 0; i < N; i++) {
NewNode tmp_l = new NewNode();
NewNode tmp_r = new NewNode();
String left = scanner.next();
if(!left.equals("-")){
tmp_l.setVal(Integer.valueOf(left));
}
String right = scanner.next();
if(!right.equals("-")){
tmp_r.setVal(Integer.valueOf(right));
}
NewNode tmp = new NewNode();
tmp.setVal(i);
tmp.setLeft(tmp_l);
tmp.setRight(tmp_r);
node.add(tmp);
}
NewNode root = GetTree(node , N);
StringBuilder sb = new StringBuilder();
sb = cengci(root , N);
String infor = sb.substring(0 , sb.length() - 1);
System.out.print(infor);
}
static NewNode GetTree(ArrayList<NewNode> node , int N){
NewNode root = node.get(0);
node.remove(0);
NewNode current = root;
int flag;
while (!node.isEmpty()){
flag = 0;
for (int i = 0; i < node.size(); i++) {
if(current.look >= 2 && current.parent != null){
current = current.parent;
i = 0;
}
NewNode newNode = node.get(i);
if(current.parent == null){
root = current;
}
if(current.left != null && current.right != null && current.left.val == newNode.val && current.right.val != -1){
current.look++;
current.left = newNode;
newNode.parent = current;
current = current.left;
flag = i;
break;
} else if (current.left != null && current.right != null && current.right.val == newNode.val && current.left.val != -1) {
current.look++;
current.right = newNode;
newNode.parent = current;
current = current.right;
flag = i;
break;
} else if (current.left != null && current.right != null && current.left.val == newNode.val && current.right.val == -1) {
current.look = current.look + 2;
current.left = newNode;
newNode.parent = current;
current = current.left;
flag = i;
break;
}else if (current.left != null && current.right != null && current.right.val == newNode.val && current.left.val == -1) {
current.look = current.look + 2;
current.right = newNode;
newNode.parent = current;
current = current.right;
flag = i;
break;
} else if (newNode.left != null && newNode.right != null && newNode.left.val == current.val && newNode.right.val != -1) {
current.parent = newNode;
newNode.left = current;
current = current.parent;
current.look++;
flag = i;
break;
}else if (newNode.left != null && newNode.right != null && newNode.right.val == current.val && newNode.left.val != -1) {
current.parent = newNode;
newNode.right = current;
current = current.parent;
current.look++;
flag = i;
break;
} else if (newNode.left != null && current.right != null && newNode.left.val == current.val && newNode.right.val == -1) {
current.parent = newNode;
newNode.left = current;
current = current.parent;
flag = i;
break;
}else if (newNode.left != null && current.right != null && newNode.right.val == current.val && newNode.left.val == -1) {
current.parent = newNode;
newNode.right = current;
current = current.parent;
flag = i;
break;
} else if (current.left.val == -1 && current.right.val == -1 && current.val != -1 && current.parent != null) {
current = current.parent;
flag = -1;
break;
}
}
if(flag != -1)
node.remove(flag);
}
return root;
}
static StringBuilder cengci(NewNode node , int n){
StringBuilder sb = new StringBuilder();
Queue<NewNode> queue = new LinkedList<>();
if(node == null){
return null;
}
int nums = 0;
queue.add(node);
while (!queue.isEmpty()){
NewNode front = queue.peek();
nums++;
if(front.right != null && front.left != null && front.right.val == -1 && front.left.val == -1 && front.val != -1)
sb.append(front.val + " ");
else if (front.right == null && front.left == null && front.val != -1) {
sb.append(front.val + " ");
}
queue.poll();
if(front.left != null){
queue.add(front.left);
}
if(front.right != null){
queue.add(front.right);
}
}
return sb;
}
}
提交的结果如下- -:
这个题我一开始是想用“拼拼图”的思想来写的,如下图:
然后这是我根据题目画的“拼图”:
这思路确实是挺麻烦的,要细致地考虑多种情况。针对上面测试样例3的提示,我也尝试了不少例子,输出没错,但就是过不了T T
然后今天早上我向老师请教了这个问题,老师说可以用顺序表,一开始就把它们的父节点找到并记录下来,之后根据顺序表构建二叉树,这可比我之前那个思路清晰多了。于是一下课,我就立马回宿舍尝试一下这个思路。
首先观察下面这个图:
仔细观察,我们可以发现可以根据每一行的Left值和Right值找到它们的父节点(即编号)。
所以经过修改后,我的代码变成了这样:
import java.util.*;
class NewNode {
int val = -1;
int look = 0;
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
NewNode left;
public NewNode getLeft() {
return left;
}
public void setLeft(NewNode left) {
this.left = left;
}
NewNode right;
public NewNode getRight() {
return right;
}
public void setRight(NewNode right) {
this.right = right;
}
NewNode parent;
public NewNode getParent() {
return parent;
}
public void setParent(NewNode parent) {
this.parent = parent;
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
NewNode node[] = new NewNode[N];
if(N > 10){
N = 10;
}
for (int i = 0; i < N; i++) {
NewNode tmp_l = new NewNode();
NewNode tmp_r = new NewNode();
String left = scanner.next();
if(!left.equals("-")){
tmp_l.setVal(Integer.valueOf(left));
}
String right = scanner.next();
if(!right.equals("-")){
tmp_r.setVal(Integer.valueOf(right));
}
NewNode tmp = new NewNode();
tmp.setVal(i);
tmp.setLeft(tmp_l);
tmp.setRight(tmp_r);
node[i] = tmp;
}
NewNode root = new NewNode();
for (int i = 0; i < node.length; i++) {
NewNode tmp = node[i];
if(tmp.left.val != -1){
NewNode tmp1 = node[tmp.left.val];
tmp1.parent = tmp;
}
if(tmp.right.val != -1){
NewNode tmp1 = node[tmp.right.val];
tmp1.parent = tmp;
}
}
int rot = 0;
for (int i = 0; i < node.length; i++) {
NewNode tmp = node[i];
if(tmp.parent == null){
root = tmp;
rot = i;
break;
}
}
NewNode tree = buildTree(rot , node);
StringBuilder sb = new StringBuilder();
sb = cengci(tree , N);
String infor = sb.substring(0 , sb.length() - 1);
System.out.print(infor);
}
static NewNode buildTree(int rot , NewNode[] node){
NewNode t = node[rot];
NewNode tr = new NewNode();
tr.val = t.val;
if(t.left.val != -1){
tr.left = buildTree(t.left.val, node);
}else tr.left = null;
if(t.right.val != -1){
tr.right = buildTree(t.right.val, node);
}else tr.right = null;
return tr;
}
static StringBuilder cengci(NewNode node , int n){
StringBuilder sb = new StringBuilder();
Queue<NewNode> queue = new LinkedList<>();
if(node == null){
return null;
}
int nums = 0;
queue.add(node);
while (!queue.isEmpty()){
NewNode front = queue.peek();
nums++;
if(front.right != null && front.left != null && front.right.val == -1 && front.left.val == -1 && front.val != -1)
sb.append(front.val + " ");
else if (front.right == null && front.left == null && front.val != -1) {
sb.append(front.val + " ");
}
queue.poll();
if(front.left != null){
queue.add(front.left);
}
if(front.right != null){
queue.add(front.right);
}
}
return sb;
}
}
在主函数中,我用数组替换了一开始用的Arrayslist(其实都差不多的- -,这个细节可以忽略)。第一个循环我用来储存输入的值;第二个循环我就开始利用上图的特性找到它们的父节点;第三个循环我用来找其根节点以及根节点所在的位置。之后用buildTree()的方法来生成二叉树。之后用StringBuilder来储存要输出的值,最后利用.substring(0 , sb.length() - 1)的技巧把多余的空格删去。
运行结果如下:
这是我写代码时试过的用例:
7
1 2
3 4
5 6
- -
- -
- -
- -
7
1 2
3 4
- -
5 6
- -
- -
- -
10
1 2
- -
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- -
7
1 -
2 3
- -
4 5
- 6
- -
- -
7
1 2
3 4
- -
- -
5 6
- -
- -
7
4 1
- -
3 0
5 6
- -
- -
- -
7
- 1
- -
3 0
4 5
6 -
- -
- -
9
1 2
3 4
- -
5 6
- -
- -
7 8
- -
- -
10
1 2
3 4
5 6
7 8
9 -
- -
- -
- -
- -
- -
7
1 4
2 3
- -
6 5
- -
- -
- -
10
1 2
3 4
8 9
5 6
- -
7 -
- -
- -
- -
- -
5
- -
- -
- -
0 2
3 1