A-二叉树的镜像&包含min函数的栈

题目19:请完成一个函数,输入一个二叉树,该函数输出它的镜像。二叉树结点定义如下。

    public class TreeNode{
        public int value;
        public TreeNode leftNode;
        public TreeNode rightNode;

        public TreeNode() {}

        public TreeNode(int value) {
            this.value = value;
        }
    }

分析:
  为了能够形成直观的印象,可以自己画一颗二叉树,然后根据照镜子的经验画出它的镜像。如下图所示。
在这里插入图片描述
  可以看出,这两棵树根结点相同,但左右两个子结点交换了位置,因此不妨直接交换根结点的两个子节结点。如下图a所示。之后发现10和6结点的子结点保持不变,继续交换这两个结点的子结点,如下图b和c所示。此变换之后的树就是原树的镜像。
在这里插入图片描述
  可得出求一棵树的镜像的过程:先遍历这棵树的每个结点,如果遍历到的结点有子结点,就交换它的两个子节点,当交换完所有非叶子结点的左右结点之后,就得到了树的镜像。
  代码如下所示:

    public static void mirrorRecursively(TreeNode pNode){
        if (pNode == null ) return;
        if (pNode.leftNode == null && pNode.rightNode == null )return;
        TreeNode temp = pNode.leftNode;
        pNode.leftNode = pNode.rightNode;
        pNode.rightNode = temp;
        if(pNode.leftNode != null) mirrorRecursively(pNode.leftNode);
        if(pNode.rightNode != null )mirrorRecursively(pNode.rightNode);
    }

  为了测试,使用下面这个辅助函数:

    public static ArrayList<Integer> printFromTopToBottom(TreeNode pTreeRoot) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        if (pTreeRoot == null) {
            return null;
        }
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(pTreeRoot);
        while (!queue.isEmpty()) {
            TreeNode treeNode = queue.poll();
            if (treeNode.leftNode != null) {
                queue.offer(treeNode.leftNode);
            }
            if (treeNode.rightNode != null) {
                queue.offer(treeNode.rightNode);
            }
            list.add(treeNode.value);
        }
        return list;
    }

  测试:

    public static void main(String[] args) {
        TreeNode pNode1 = new TreeNode(8);
        TreeNode pNode2 = new TreeNode(6);
        TreeNode pNode3 = new TreeNode(10);
        TreeNode pNode4 = new TreeNode(5);
        TreeNode pNode5 = new TreeNode(7);
        TreeNode pNode6 = new TreeNode(9);
        TreeNode pNode7 = new TreeNode(11);

        pNode1.leftNode = pNode2;
//        pNode1.rightNode = pNode3;
        pNode2.leftNode = pNode4;
        pNode2.rightNode = pNode5;
//        pNode3.leftNode = pNode6;
//        pNode3.rightNode = pNode7;

        mirrorRecursively(pNode1);
        System.out.println(printFromTopToBottom(pNode1));

        // 只有一个结点
        TreeNode node = new TreeNode(8);
        mirrorRecursively(node);
        System.out.println(printFromTopToBottom(node));

        // 空结点
        mirrorRecursively(null);
    }

题目21:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数,在该栈中,调用min、push及pop的时间复杂度都是O(1)。
分析:
  可能会想到在栈里添加一个成员变量存放最小值的元素,每次压入一个新元素的时候,如果该元素比当前最小的元素还要小,则更新最小元素。但是当最小元素被弹出栈时,如何找到下一个最小元素呢?
  是不是可以把每次的最小元素(之前的最小元素和压入栈的新元素两者的较小值)都保存到另外一个辅助栈里呢?分析过程如下表所示。首先往空的栈里压入元素3,显然现在最小值是3,把最小值压入辅助栈;接着往数据栈里压入4,最小值仍为3,所以依然往辅助栈压入3;继续往数据栈里压入2,此时最小元素时2,因此往辅助栈里压入2…当把最小元素从数据栈弹出时,同时弹出辅助栈的栈顶元素,此时辅助栈的栈顶元素就是下一个最小值。

步骤操作数据栈辅助栈最小值
1压入3333
2压入43,43,33
3压入23,4,23 ,3,22
4压入13,4,2,13 ,3,2,11
5弹出3,4,23 ,3,22
6弹出3,43,33
7压入03,4,03,3,00

  代码如下所示:

    private static Stack<Integer> stack = new Stack();
    private static Stack<Integer> minSatck = new Stack();

    public static void push(int value) {
        stack.push(value);
        if (minSatck.size() == 0 || value < minSatck.peek())
            minSatck.push(value);
        else
            minSatck.push(minSatck.peek());
    }

    public static void pop() {
        if (stack.size() == 0 && minSatck.size() == 0) throw new RuntimeException("栈是空的");
        stack.pop();
        minSatck.pop();
    }

    public static Integer min() {
        if (stack.size() == 0 && minSatck.size() == 0) throw new RuntimeException("栈是空的");
        return minSatck.peek();
    }


    public static void main(String[] args) {
        push(5);
        push(6);
        System.out.println(min());
        push(4);
        push(1);
        System.out.println(min());
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值