public static void reverseLevelOrderPrint(TreeNode<Integer> root) {

        if(root == null) {
            return;
        }

        Queue<TreeNode<Integer>> queue = new LinkedList<>();
        queue.offer(root);
        Stack<ValueAndLevel> stack = new Stack<>();

        int currentLevel = 0;
        int currentLevelCount = 1;
        int nextLevelCount = 0;

        while(!queue.isEmpty()) {
            TreeNode<Integer> current = queue.poll();
            currentLevelCount--;

            stack.push(new ValueAndLevel(current.getValue(), currentLevel));

            TreeNode<Integer> left = current.getLeft();
            TreeNode<Integer> right = current.getRight();

            if(left != null) {
                nextLevelCount++;
                queue.offer(left);
            }

            if(right != null) {
                nextLevelCount++;
                queue.offer(right);
            }

            if(currentLevelCount == 0) {
                currentLevel++;
                currentLevelCount = nextLevelCount;
                nextLevelCount = 0;
            }
        }

        currentLevel = -1;
        while(!stack.isEmpty()) {
            ValueAndLevel val = stack.pop();

            if(currentLevel == -1) {
                currentLevel = val.getLevel();
            } else if(val.getLevel() < currentLevel) {
                currentLevel = val.getLevel();
                System.out.println();
            }

            System.out.print(val.getValue() + " ");
        }
    }