与二叉树有关的编程题的Java代码实现

该文章几乎包含了所有与二叉树相关的基础面试题,其中包括二叉树的四种遍历方法:前序遍历,中序遍历,后续遍历,层次遍历。

算法题包括:

二叉树的序列化和反序列化

给定一颗二叉搜索树,请找出其中的第k大的结点。例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中, 按结点数值大小顺序第三个结点的值为4。

package test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;

import org.junit.Test;

class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}

public class Solution {
    /**
     * 二叉树的前序序列化
     *
     * @param root
     * @return
     */
    String Serialize(TreeNode root) {
        if (root == null)
            return null;
        StringBuilder str = new StringBuilder();
        SerializeRe(root, str);
        return str.toString();
    }

    /**
     * 二叉树的前序序列化递归方法
     *
     * @param root
     * @param str
     */
    public void SerializeRe(TreeNode root, StringBuilder str) {
        if (root == null) {
            str.append("#,");
            return;
        } else {
            str.append(root.val);
            str.append(",");
            SerializeRe(root.left, str);
            SerializeRe(root.right, str);
        }
        return;
    }

    /**
     * 前序反序列化
     *
     * @param str
     * @return
     */
    TreeNode Deserialize(String str) {
        if (str == null || str.length() == 0 || str.equals("#"))
            return null;
        String[] value = str.split(",");
        return DeserializeRe(value);
    }

    int index = 0;

    /**
     * 前序反序列化递归方法
     *
     * @param str
     * @return
     */
    public TreeNode DeserializeRe(String[] str) {
        TreeNode root = new TreeNode(-1);
        if (str[index].equals("#") || index > str.length) {
            return null;
        }
        root.val = Integer.valueOf(str[index]);
        index++;
        root.left = DeserializeRe(str);
        index++;
        root.right = DeserializeRe(str);
        return root;
    }

    /**
     * 根据数组从上到下构造一棵二叉树(即完全二叉树)
     *
     * @param a
     * @param index
     * @return
     */
    public TreeNode buildTreeLevel(int[] a) {
        if (a == null || a.length == 0)
            return null;
        return buildTreeLevelRe(a, 0);
    }

    private TreeNode buildTreeLevelRe(int[] a, int index) {
        TreeNode root = new TreeNode(-1);
        root.val = a[index];
        if (index * 2 + 1 <= a.length - 1) {
            root.left = buildTreeLevelRe(a, index * 2 + 1);
        }
        if (index * 2 + 2 <= a.length - 1) {
            root.right = buildTreeLevelRe(a, index * 2 + 2);
        }
        return root;
    }

    /**
     * 前序遍历二叉树
     *
     * @param root
     */
    public void preOderTree(TreeNode root) {
        if (root == null)
            return;
        System.out.println(root.val);
        preOderTree(root.left);
        preOderTree(root.right);
        return;
    }

    /**
     * 中序遍历二叉树
     *
     * @param root
     */
    public void inOderTree(TreeNode root) {
        if (root == null)
            return;
        inOderTree(root.left);
        System.out.println(root.val);
        inOderTree(root.right);
        return;
    }

    /**
     * 后序遍历二叉树
     *
     * @param root
     */
    public void postOderTree(TreeNode root) {
        if (root == null)
            return;
        postOderTree(root.left);
        postOderTree(root.right);
        System.out.println(root.val);
        return;
    }

    /**
     * 层次遍历二叉树
     *
     * @param root
     */
    public void levelOderTree(TreeNode root) {
        if (root == null)
            return;
        Queue<TreeNode> nodes = new LinkedList<TreeNode>();
        nodes.add(root);
        while (!nodes.isEmpty()) {
            TreeNode node = nodes.poll();
            System.out.println(node.val);
            if (node.left != null) {
                nodes.add(node.left);
            }
            if (node.right != null) {
                nodes.add(node.right);
            }
        }
    }

    /**
     * 给定一颗二叉搜索树,请找出其中的第k大的结点。例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中, 按结点数值大小顺序第三个结点的值为4。
     * 解法一:时间复杂度O(k),空间复杂度O(1)
     *
     * @param root
     * @param k
     * @return
     */
    int count = 0;// 计数器

    public TreeNode KthNodeRe(TreeNode root, int k) {
        if (root != null) {
            TreeNode node = KthNodeRe(root.left, k);
            if (node != null)
                return node;
            count++;
            if (count == k)
                return root;
            node = KthNodeRe(root.right, k);
            if (node != null)
                return node;
        }
        return null;
    }

    ArrayList<TreeNode> arr = new ArrayList<TreeNode>();

    /**
     * 解法二:时间复杂度O(n),空间复杂度O(n)
     *
     * @param pRoot
     * @param k
     * @return
     */
    public TreeNode KthNode(TreeNode pRoot, int k) {
        if (pRoot == null || k <= 0)
            return null;
        InOder(pRoot);
        return k > arr.size() ? null : arr.get(arr.size() - k);
    }

    public void InOder(TreeNode pRoot) {
        if (pRoot == null)
            return;
        InOder(pRoot.left);
        arr.add(pRoot);
        InOder(pRoot.right);
    }

    /**
     * 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,
     * 那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,
     * 那么中位数就是所有数值排序之后中间两个数的平均值
     * @param num
     */
    private PriorityQueue<Integer> minHeap = new PriorityQueue<>();
    private PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(
            new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o2 - o1;
                }
            });
    public void Insert(Integer num) {
        if (count % 2 == 0) {
            // 1.新加入的元素先入到大根堆,由大根堆筛选出堆中最大的元素
            maxHeap.offer(num);
            int filteredMaxNum = maxHeap.poll();
            // 2.筛选后的【大根堆中的最大元素】进入小根堆
            minHeap.offer(filteredMaxNum);
        } else {
            // 1.新加入的元素先入到小根堆,由小根堆筛选出堆中最小的元素
            minHeap.offer(num);
            int filteredMinNum = minHeap.poll();
            // 2.筛选后的【小根堆中的最小元素】进入大根堆
            maxHeap.offer(filteredMinNum);
        }
        count++;
    }

    public Double GetMedian() {
        if (count % 2 == 0) {
            return new Double((minHeap.peek() + maxHeap.peek())) / 2;
        } else {
            return new Double(minHeap.peek());
        }
    }

    @Test
    public void testDeserialize() {
        String str = "1,2,4,#,#,5,#,#,3,#,#";
        TreeNode root = Deserialize(str);
        preOderTree(root);
    }

    @Test
    public void testBuildTreePre() {
        String str = "1,2,4,#,#,5,#,#,3,#,#";
        TreeNode root = Deserialize(str);
        // preOderTree(root);
        String serialize = Serialize(root);
        System.out.println(serialize);
    }

    @Test
    public void testBuildTreeLevel() {
        int[] a = { 1, 2, 3, 4, 5 };
        TreeNode root = buildTreeLevel(a);
        inOderTree(root);
    }

    @Test
    public void testBuildTreeKthNode() {
        int[] a = { 4, 2, 5, 1, 3 };
        TreeNode root = buildTreeLevel(a);
        inOderTree(root);
    }
}
时间: 2024-10-09 14:08:54

与二叉树有关的编程题的Java代码实现的相关文章

去哪儿网2017校招在线笔试(前端工程师)编程题及JavaScript代码

编程题很简单.整个试卷结构为: 一.问答题: 对前端的理解,了解哪些框架库? 二.在线编程题:身份证分组 如下第一道:身份证分组 三.在线编程题:身份证分组.统计字符.酒店价格(三选二) 如下第二三四道题中三选二作答. 我也搞不懂为什么有两部分编程题~~~下面详细说一说编程题目及JS代码实现: 第一道:身份证分组 代码: 1 var line; 2 while(line = read_line()){ 3 while(line.indexOf(" ") != -1){ 4 line =

剑指Offer编程题(Java实现)——二维数组中的查找

题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 解题思路 根据排序特点,该二维数组中的一个数,小于它的数一定在其左边,大于它的数一定在其下边. 因此,从右上角开始查找,就可以根据 target 和当前元素的大小关系来缩小查找区间,当前元素的查找区间为左下角的所有元素. 时间复杂度 O(M + N),空间复杂度 O(1).其中 M 为行数,N

剑指Offer编程题(Java实现)——反转链表

题目描述 输入一个链表,反转链表后,输出新链表的表头. 思路一 使用头插法迭代进行反转 实现 /* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } }*/ public class Solution { public ListNode ReverseList(ListNode head) { ListNode newHead = new ListNode(-1

中国MOOC_面向对象程序设计——Java语言_期末考试编程题_1细胞自动机

期末考试编程题 返回 这是期末考试的编程题 温馨提示: 1.本次考试属于Online Judge题目,提交后由系统即时判分. 2.学生可以在考试截止时间之前提交答案,系统将取其中的最高分作为最终成绩. 1 细胞自动机(30分) 题目内容: 这是细胞自动机的非图形版本.细胞自动机是指在一个二维网格内,每一个网格是一个细胞.每个细胞有活和死两种状态. 初始时刻,有些细胞是活的,有些细胞是死的.自动机的每一步,根据每个细胞周围8个格子内的其他细胞的生存情况决定这个细胞下一步是否存活.具体的规则如下:

java第四章编程题(初学篇)

代码: 1 /* 2 test.java 3 */ 4 package test; 5 public class test { 6 public static void main(String args[] ) 7 { 8 CPU ccp= new CPU(); 9 HardDisk hhd=new HardDisk(); 10 PC pc =new PC(); 11 ccp.setSpeed(2200); 12 hhd.setAmount(200); 13 pc.setCPU(ccp); 14

java学习之第五章编程题示例(初学篇)

1 /* 2 Animal.java 3 */ 4 package animal; 5 6 public abstract class Animal { 7 public abstract void cry(); 8 public abstract String getanimalName(); 9 } 1 //Dog.java 2 package animal; 3 4 public class Dog extends Animal 5 { 6 7 String aa="旺旺"; 8

中国MOOC_零基础学Java语言_期末考试的编程题_1二进制的前导的零

期末考试的编程题 返回 这是期末考试的编程题,在60分钟内,你可以多次提交,直到正确为止. 温馨提示: 1.本次考试属于Online Judge题目,提交后由系统即时判分. 2.学生可以在考试截止时间之前提交答案,系统将取其中的最高分作为最终成绩. 1 二进制的前导的零(10分) 题目内容: 计算机内部用二进制来表达所有的值.一个十进制的数字,比如18,在一个32位的计算机内部被表达为00000000000000000000000000011000.可以看到,从左边数过来,在第一个1之前,有27

程序设计入门—Java语言 第六周编程题 1 单词长度(4分)

第六周编程题 依照学术诚信条款,我保证此作业是本人独立完成的. 1 单词长度(4分) 题目内容: 你的程序要读入一行文本,其中以空格分隔为若干个单词,以'.'结束.你要输出这行文本中每个单词的长度.这里的单词与语言无关,可以包括各种符号,比如"it's"算一个单词,长度为4.注意,行中可能出现连续的空格. 输入格式: 输入在一行中给出一行文本,以'.'结束,结尾的句号不能计算在最后一个单词的长度内. 输出格式: 在一行中输出这行文本对应的单词的长度,每个长度之间以空格隔开,行末没有最后

java基础编程题

java基础编程题 1.打印出如下图案 1 public class Prog19{ 2 public static void main(String[] args){ 3 int n = 5; 4 printStar(n); 5 } 6 7 //打印星星 8 private static void printStar(int n){ 9 //打印上半部分 10 for(int i=0;i<n;i++){ 11 for(int j=0;j<2*n;j++){ 12 if(j<n-i) 1