1. 程式人生 > >《程序員面試指南》第一章 棧和隊列 構造數組的MaxTree

《程序員面試指南》第一章 棧和隊列 構造數組的MaxTree

tac HA int markdown tno tree isempty right inorder

題目

給出一個無重復元素的數組,構造此數組的MaxTree,

java代碼

/**
 * @Description: 構造數組的MaxTree
 * @Author: lizhouwei
 * @CreateDate: 2018/4/5 22:16
 * @Modify by:
 * @ModifyDate:
 */
public class Chapter1_8 {

    public Node getMaxTree(int[] arr) {
        if (arr == null) {
            return null;
        }
        int length = arr.length;
        Node[] nodes = new Node[length];
        //初始化Node數組
        for (int i = 0; i < length; i++) {
            nodes[i] = new Node(arr[i]);
        }
        //存放當前節點往左 第一個大於當前節點的節點
        Map<Node, Node> leftMap = new HashMap<Node, Node>();
        //存放當前節點往右 第一個大於當前節點的節點
        Map<Node, Node> rightMap = new HashMap<Node, Node>();
        //存放遍歷到節點
        Stack<Node> stack = new Stack<Node>();
        for (int i = 0; i < length; i++) {
            //關鍵地方,判斷棧頂元素的值是否小於當前元素的值,如果小於則在map中記錄棧頂元素的往左數第一個元素
            while (!stack.isEmpty() && stack.peek().value < nodes[i].value) {
                popStackToMap(stack, leftMap);
            }
            //存放當前元素,前提保證棧中沒有比小的元素
            stack.push(nodes[i]);
        }
        //如果棧中還有元素,則循環獲取棧中元素的往左數第一個大於他的元素
        while (!stack.isEmpty()) {
            popStackToMap(stack, leftMap);
        }

        for (int i = length - 1; i >= 0; i--) {
            //關鍵地方,判斷棧頂元素的值是否小於當前元素的值,如果小於則在map中記錄棧頂元素的往右數第一個元素
            while (!stack.isEmpty() && stack.peek().value < nodes[i].value) {
                popStackToMap(stack, rightMap);
            }
            //存放當前元素,前提保證棧中沒有比小的元素
            stack.push(nodes[i]);
        }
        //如果棧中還有元素,則循環獲取棧中元素的往右數第一個大於他的元素
        while (!stack.isEmpty()) {
            popStackToMap(stack, rightMap);
        }
        //再將 每個元素 左右 最大的元找見後,開始構造MaxTree
        Node head = null;
        for (int i = 0; i < length; i++) {
            Node node = nodes[i];
            Node leftNode = leftMap.get(node);
            Node rightNode = rightMap.get(node);
            //左右最大的元素都為空,則此元素是數組中最大,作為根節點
            if (leftNode == null && rightNode == null) {
                head = node;
            } else if (leftNode == null) {
                if (rightNode.left == null) {
                    rightNode.left = node;
                } else {
                    rightNode.right = node;
                }
            } else if (rightNode == null) {
                if (leftNode.left == null) {
                    leftNode.left = node;
                } else {
                    leftNode.right = node;
                }
            } else {
                Node parent = leftNode.value < rightNode.value ? leftNode : rightNode;
                if (parent.left == null) {
                    parent.left = node;
                } else {
                    parent.right = node;
                }
            }
        }
        return head;
    }

    public void popStackToMap(Stack<Node> stack, Map<Node, Node> map) {
        Node node = stack.pop();
        if (stack.isEmpty()) {
            map.put(node, null);
        } else {
            map.put(node, stack.peek());
        }
    }

    //簡單的用遞歸中序遍歷一下生成的MaxTree
    public void recInOrder(Node head) {
        if (head == null) {
            return;
        }
        recInOrder(head.left);
        System.out.print(head.value + " ");
        recInOrder(head.right);
    }

    //測試
    public static void main(String[] args) {
        Chapter1_8 chapter = new Chapter1_8();
        int[] arr = {3, 4, 5, 1, 2};
        Node head = chapter.getMaxTree(arr);
        chapter.recInOrder(head);
    }

}

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

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

《程序員面試指南》第一章 棧和隊列 構造數組的MaxTree