二叉树/打表技巧

目录

 二叉树

二叉树的先序、中序、后续遍历

什么是递归序

非递归方式实现

实现二叉树的按层遍历

求二叉树的最大宽度

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

如何设计一个打印整棵树的打印函数

 给你二叉树中的某个节点,返回该节点的后继节点

 纸条对折问题

二叉树的递归套路描述

二叉树的递归套路实现

套路实践-给定一颗二叉树的头节点head,返回这颗二叉树是不是平衡二叉树

套路实践-给定一棵二叉树的头节点head,任何俩个节点之间都存在距离,返回整颗二叉树的最大距离

套路实践-给定一棵二叉树的头节点head,返回这颗二叉树中最大的二叉搜索子树的头节点。(返回size)

套路实践-派对的最大快乐值

打表技巧(打表找规律)

题目一:俩种袋子装苹果,一个装6个,一个装8个。问N个苹果,返回至少使用袋子的数量。

 题目二:N份青草,牛先吃,羊后吃。每次吃4的某次方,谁先吃完谁获胜。问给定N,返回谁赢

题目三:定义一种数,可以表示成若干连续整数和的数(数量>1)。


 二叉树

二叉树的先序、中序、后续遍历

先序:任何子树的处理顺序都是,先头结点、再左子树、然后右子树

中序:任何子树的处理顺序都是,先左子树、再头节点、然后右子树

后序:任何子树的处理顺序都是,先左子树、再右子树、然后头节点

递归方式实现

    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int v) {
            value = v;
        }
    }

    public static void f(Node head) {
        if (head == null) {
            return;
        }
        // 1
        f(head.left);
        // 2
        f(head.right);
        // 3
    }

    // 先序打印所有节点
    public static void pre(Node head) {
        if (head == null) {
            return;
        }
        System.out.println(head.value);
        pre(head.left);
        pre(head.right);
    }

    public static void in(Node head) {
        if (head == null) {
            return;
        }
        in(head.left);
        System.out.println(head.value);
        in(head.right);
    }

    public static void pos(Node head) {
        if (head == null) {
            return;
        }
        pos(head.left);
        pos(head.right);
        System.out.println(head.value);
    }

什么是递归序

非递归方式实现

     先序非递归实现

               头 弹出打印  右孩子 左孩子        弹 右 左

 

 后序非递归实现

        俩个栈实现方式

        一个栈实现方式(用变量去卡边界)

//        H 等于 head   c 等于 null
//        H 永远跟踪 上次打印的节点
    public static void pos2(Node h) {
//        H 等于 head   c 等于 null
//        H 永远跟踪 上次打印的节点
        System.out.print("pos-order: ");
        if (h != null) {
            Stack<Node> stack = new Stack<Node>();
            stack.push(h);
            Node c = null;
            while (!stack.isEmpty()) {
                c = stack.peek();
                // 左孩子不等于null  h不等于左孩子 h不等于右孩子
                if (c.left != null && h != c.left && h != c.right) {
                    stack.push(c.left);
                    // 右孩子不等于null  h 不等于右孩子
                } else if (c.right != null && h != c.right) {
                    stack.push(c.right);
                } else {
                    System.out.print(stack.pop().value + " ");
                    h = c;
                }
            }
        }
        System.out.println();
    }

 中序非递归实现

    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int v) {
            value = v;
        }
    }

    public static void pre(Node head) {
        System.out.print("pre-order: ");
        if (head != null) {
            Stack<Node> stack = new Stack<Node>();
            stack.add(head);
            //判断栈是否为空
            while (!stack.isEmpty()) {
                head = stack.pop();
                System.out.print(head.value + " ");
                if (head.right != null) {
                    stack.push(head.right);
                }
                if (head.left != null) {
                    stack.push(head.left);
                }
            }
        }
        System.out.println();
    }

    public static void in(Node cur) {
        System.out.print("in-order: ");
        if (cur != null) {
            Stack<Node> stack = new Stack<Node>();
            while (!stack.isEmpty() || cur != null) {
                if (cur != null) {
                    stack.push(cur);
                    // 来到
                    cur = cur.left;
                } else {
                    cur = stack.pop();
                    System.out.print(cur.value + " ");
                    cur = cur.right;
                }
            }
        }
        System.out.println();
    }

    public static void pos1(Node head) {
        //利用俩个栈实现   头(弹) 左 右
        // 后一个逆序写出  也就是pop出来   栈先进后出
        System.out.print("pos-order: ");
        if (head != null) {
            Stack<Node> s1 = new Stack<Node>();
            Stack<Node> s2 = new Stack<Node>();
            s1.push(head);
            while (!s1.isEmpty()) {
                head = s1.pop(); // 头 右 左
                s2.push(head);
                if (head.left != null) {
                    s1.push(head.left);
                }
                if (head.right != null) {
                    s1.push(head.right);
                }
            }
            // 左 右 头
            while (!s2.isEmpty()) {
                System.out.print(s2.pop().value + " ");
            }
        }
        System.out.println();
    }

    // 一个栈实现后序遍历
    public static void pos2(Node h) {
//        H 等于 head   c 等于 null
//        H 永远跟踪 上次打印的节点
        System.out.print("pos-order: ");
        if (h != null) {
            Stack<Node> stack = new Stack<Node>();
            stack.push(h);
            Node c = null;
            while (!stack.isEmpty()) {
                c = stack.peek();
                // 左孩子不等于null  h不等于左孩子 h不等于右孩子
                if (c.left != null && h != c.left && h != c.right) {
                    stack.push(c.left);
                    // 右孩子不等于null  h 不等于右孩子
                } else if (c.right != null && h != c.right) {
                    stack.push(c.right);
                } else {
                    System.out.print(stack.pop().value + " ");
                    h = c;
                }
            }
        }
        System.out.println();
    }

实现二叉树的按层遍历

1)其实就是宽度优先遍历,用队列

2)可以通过设置flag变量的方式,来发现某一层的结束(看题目)

    public static class Node {
        public int value;
        public Node left;
        public Node right;
        public Node(int v) {
            value = v;
        }
    }

    public static void level(Node head) {
        if (head == null) {
            return;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(head);
        while (!queue.isEmpty()) {
            Node cur = queue.poll();
            System.out.println(cur.value);
            if (cur.left != null) {
                queue.add(cur.left);
            }
            if (cur.right != null) {
                queue.add(cur.right);
            }
        }
    }

求二叉树的最大宽度

HashMap方式

    public static class Node {
        public int value;
        public Node left;
        public Node right;
        public Node(int v) {
            value = v;
        }
    }

    public static int maxWidthUseMap(Node head) {
        if (head == null) {
            return 0;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(head);
        //key在哪一层,value
        HashMap<Node, Integer> levelMap = new HashMap<>();
        levelMap.put(head, 1);  // head 在第一层
        int curLevel = 1; //当前你正在统计哪一层的宽度
        int curLevelNodes = 0; //当前层curLeve1层, 宽度目前是多少.
        int max = 0;
        while (!queue.isEmpty()) {
            Node cur = queue.poll();
            // curNodeLevel 获取当前值的层数
            int curNodeLevel = levelMap.get(cur);
            if (cur.left != null) {
                levelMap.put(cur.left, curNodeLevel + 1);
                qu
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值