构造数据的MaxTree

题目描述

一个数组的MaxTree定义如下:
 数组必须没有重复元素。
 MaxTree是一棵二叉树, 数组的每一个值对应一个二叉树节点。
 包括MaxTree树在内且在其中的每一棵子树上, 值最大的节点都是树的头。
 给定一个没有重复元素的数组arr, 写出生成这个数组的MaxTree的函数, 要求如果数组长度为N, 则时间复杂度为O(N)、 额外空间复杂度为O(N)。

解题思路

解法一:可以利用堆,构造堆的时间复杂度是O(N)
解法二:利用单调栈求出数组中每个位置左右最近的比它大的值,然后让左右都为null的结点作为头结点,只有左边大的的作为左边结点的左孩子,只有右边结点大的作为右边结点的右孩子,左右比它大的都有的,选择两个中较小的,作为较小的结点的孩子

代码

package TestNode.StackAndQueue;

import java.util.HashMap;
import java.util.Stack;

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

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

    // 方法一:通过单调栈实现
    public static Node getMaxTree(int[] arr) {
        Node[] nArr = new Node[arr.length];
        for (int i = 0; i != arr.length; i++) {
            nArr[i] = new Node(arr[i]);
        }
        Stack<Node> stack = new Stack<>();
        HashMap<Node,Node> lBigMap = new HashMap<>();
        HashMap<Node,Node> rBigMap = new HashMap<>();
        for (int i = 0; i != nArr.length; i++) {
            Node curNode = nArr[i];
            while ((!stack.isEmpty()) && stack.peek().value < curNode.value) {
                popStackSetMap(stack,lBigMap);
            }
            stack.push(curNode);
        }
        while (!stack.isEmpty()) {
            popStackSetMap(stack,lBigMap);
        }
        for (int i = nArr.length - 1; i != -1; i--) {
            Node curNode = nArr[i];
            while ((!stack.isEmpty()) && stack.peek().value < curNode.value) {
                popStackSetMap(stack,rBigMap);
            }
            stack.push(curNode);
        }
        while (!stack.isEmpty()) {
            popStackSetMap(stack,rBigMap);
        }
        Node head = null;
        for (int i = 0; i != nArr.length; i++) {
            Node curNode = nArr[i];
            Node left = lBigMap.get(curNode);
            Node right = rBigMap.get(curNode);
            if (left == null && right == null) {
                head = curNode;
            } else if (left == null) {
                if (right.left == null) {
                    right.left = curNode;
                } else {
                    right.right = curNode;
                }
            } else if (right == null) {
                if (left.left == null) {
                    left.left = curNode;
                } else {
                    left.right = curNode;
                }
            } else {
                Node parent = left.value < right.value ? left : right;
                if (parent.left == null) {
                    parent.left = curNode;
                } else {
                    parent.right = curNode;
                }
            }
        }
        return head;
    }

    private static void popStackSetMap(Stack<Node> stack, HashMap<Node, Node> map) {
        Node popNode = stack.pop();
        if (stack.isEmpty()) {
            map.put(popNode, null);
        } else {
            map.put(popNode,stack.peek());
        }
    }

    // 方法二: 通过堆实现
    public static Node getMaxTree2(int[] arr){
        Node[] nArr = new Node[arr.length];
        for (int i = 0; i < arr.length; i++) {
            nArr[i] = new Node(arr[i]);
        }

        for (int i = 0; i < nArr.length; i++) {
            heapfiyInsert(nArr, i);
        }
        for (int i = 0; i < nArr.length; i++) {
            if (2*i+1 < nArr.length){
                nArr[i].left = nArr[2*i+1];
            }
            if (2*i+2 < nArr.length){
                nArr[i].right = nArr[2*i+2];
            }
        }
        return nArr[0];
    }

    static void heapfiyInsert(Node[] nArr, int index){
        while (nArr[index].value > nArr[(index-1)/2].value){
            swap(nArr, index, (index-1)/2);
            index = (index-1)/2;
        }
    }

    static void swap(Node[] nArr, int a, int b){
        Node temp = nArr[a];
        nArr[a] = nArr[b];
        nArr[b] = temp;
    }

    public static void main(String[] args) {
        int[] arr = new int[]{3,4,1,2};
//        getMaxTree(arr);
        getMaxTree2(arr);
    }

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值