华为机试:完全二叉树非叶子部分后序遍历

【编程题目 | 200分】完全二叉树非叶子部分后序遍历 [ 200 / 中等 ]

完全二叉树非叶子部分后序遍历
题目描述:

给定一个以顺序储存结构存储整数值的完全二叉树序列(最多1000个整数),请找出此完全二叉树的所有非叶子节点部分,然后采用后序遍历方式将此部分树(不包含叶子)输出。

1、只有一个节点的树,此节点认定为根节点(非叶子)。

2、此完全二叉树并非满二叉树,可能存在倒数第二层出现叶子或者无右叶子的情况

其他说明:二叉树的后序遍历是基于根来说的,遍历顺序为:左-右-根

输入描述

一个通过空格分割的整数序列字符串

输出描述

非叶子部分树结构

示例 1:
输入
1 2 3 4 5 6 7
输出
2 3 1
说明

找到非叶子部分树结构,然后采用后序遍历输出

思路分析:

这道题首先考察二叉树的结构,是选择用类去构造二叉树的结构,还是直接使用数组去表示二叉树的结构,这里两种方法都实现一下。

  1. Node类构造数据结构,在用leetcode刷题时,都是构造好的二叉树,只需要直接调用即可,这里可以通过这道题学习一下自己构造二叉树的结构。
  2. 数组实现二叉树,因为这道题是一棵完全二叉树,所以不需要用-1去判断位置是不是空节点,左右子树的节点分别存储在下标2N和2N+1。

然后就是删除叶子节点,后序遍历,这些都是二叉树的常规算法思路。可以直接使用递归方法去实现。

参考代码:

Java代码实现:

  1. Node类实现二叉树数据结构
import java.util.*;

public class postTraversal {

    static class Node {  // 构造二叉树数据结构
        private int val;
        private Node left;
        private Node right;

        public Node() {
        }

        public Node(int val) {
            this.val = val;
        }

        public Node(int val, Node left, Node right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

    private static Queue<Integer> queue = new ArrayDeque<>();
    private static Queue<Node> nodes = new ArrayDeque<>();

    public static Node build() {  // 构建二叉树
        Node root = new Node(queue.poll());
        nodes.add(root);

        while (!nodes.isEmpty()) {
            Node top = nodes.poll();

            if (!queue.isEmpty()) {
                Node left = new Node(queue.poll());
                top.left = left;
                nodes.add(left);
            } else {
                break;
            }

            if (!queue.isEmpty()) {
                Node right = new Node(queue.poll());
                top.right = right;
                nodes.add(right);
            } else {
                break;
            }
        }
        return root;
    }


    public static Node remove(Node root) { // 递归删除叶子节点
        if (root == null) {
            return null;
        }
        if (root.left == null && root.right == null) {
            return null;
        }
        root.left = remove(root.left);
        root.right = remove(root.right);
        return root;
    }

    public static void postTravel(Node root, List<String> p) { // 递归后序遍历
        if (root == null) {
            return;
        }
        postTravel(root.left, p);
        postTravel(root.right, p);
        p.add(String.valueOf(root.val));
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] str = in.nextLine().split(" ");
        for (String s : str) {
            queue.add(Integer.parseInt(s));
        }
        Node root = build(); // 构建二叉树
        remove(root);  // 递归删除叶子节点
        List<String> res = new ArrayList<>();
        postTravel(root, res);  // 递归后序遍历
        System.out.print(String.join(" ", res));
    }
}
  1. 数组实现二叉树数据结构
import java.util.*;

public class postTravel_Array {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] str = in.nextLine().split(" ");
        List<Integer> res = new ArrayList<>();
        for (String s : str) {
            res.add(Integer.parseInt(s));
        }
        List<Integer> index = new ArrayList<>();
        dfs(res, 0, index);
        res.removeAll(index);  // 需要注意删除对应索引数据的问题
        List<String> ans = new ArrayList<>();
        postTravel(res, 0, ans);  // 递归后序遍历
        System.out.print(String.join(" ", ans));

    }
    private static void dfs(List<Integer> res, int idx, List<Integer> index) {  // 返回叶子节点对应索引
        if (idx >= res.size()) {
            return;
        }
        if (isLeaf(res, idx)) {
            index.add(res.get(idx));
        } else {
            dfs(res, 2 * idx + 1, index);  // 递归左叶子节点
            dfs(res, 2 * idx + 2, index);  // 递归右叶子节点
        }
    }
    private static boolean isLeaf(List<Integer> res, int idx) {  // 判断是否是叶子节点
        return ((2 * idx + 1 >= res.size() ) && (2 * idx + 2 >= res.size()));
    }
    private static void postTravel(List<Integer> res, int idx, List<String> p) { // 递归后序遍历
        if (idx >= res.size()) {
            return;
        }
        postTravel(res, 2 * idx + 1, p);
        postTravel(res, 2 * idx + 2, p);
        p.add(String.valueOf(res.get(idx)));
    }
}

注意:List的循环删除问题,根据索引删除的话,索引会发生变化。这里采用两个list,一个list存储需要删除的值,直接直接从一个list删除另一个list,调用了removeAll()方法,但效率较低,可以采用哈希表存储再进行删除。或者在删除索引时,使用迭代器写法。

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值