protected RegressionTree buildNumLeafLimitedTree(Instances instances, int maxNumLeaves) {
		RegressionTree tree = new RegressionTree();
		final int limit = 5;
		// stats[0]: totalWeights
		// stats[1]: sum
		// stats[2]: weightedMean
		// stats[3]: splitEval
		double[] stats = new double[4];
		Map<TreeNode, Double> nodePred = new HashMap<>();
		Map<TreeNode, Dataset> datasets = new HashMap<>();
		Dataset dataset = null;
		if (this.cache != null) {
			dataset = Dataset.create(this.cache, instances);
		} else {
			dataset = Dataset.get(instances);
		}
		PriorityQueue<Element<TreeNode>> q = new PriorityQueue<>();
		tree.root = createNode(dataset, limit, stats);
		q.add(new Element<TreeNode>(tree.root, stats[2]));
		datasets.put(tree.root, dataset);
		nodePred.put(tree.root, stats[1]);

		int numLeaves = 0;
		while (!q.isEmpty()) {
			Element<TreeNode> elemt = q.remove();
			TreeNode node = elemt.element;
			Dataset data = datasets.get(node);
			if (!node.isLeaf()) {
				TreeInteriorNode interiorNode = (TreeInteriorNode) node;
				Dataset left = new Dataset(data.instances);
				Dataset right = new Dataset(data.instances);
				split(data, interiorNode, left, right);

				interiorNode.left = createNode(left, limit, stats);
				if (!interiorNode.left.isLeaf()) {
					nodePred.put(interiorNode.left, stats[2]);
					q.add(new Element<TreeNode>(interiorNode.left, stats[3]));
					datasets.put(interiorNode.left, left);
				} else {
					numLeaves++;
				}
				interiorNode.right = createNode(right, limit, stats);
				if (!interiorNode.right.isLeaf()) {
					nodePred.put(interiorNode.right, stats[2]);
					q.add(new Element<TreeNode>(interiorNode.right, stats[3]));
					datasets.put(interiorNode.right, right);
				} else {
					numLeaves++;
				}

				if (numLeaves + q.size() >= maxNumLeaves) {
					break;
				}
			}
		}

		// Convert interior nodes to leaves
		Map<TreeNode, TreeNode> parent = new HashMap<>();
		traverse(tree.root, parent);
		while (!q.isEmpty()) {
			Element<TreeNode> elemt = q.remove();
			TreeNode node = elemt.element;

			double prediction = nodePred.get(node);
			TreeInteriorNode interiorNode = (TreeInteriorNode) parent.get(node);
			if (interiorNode.left == node) {
				interiorNode.left = new RegressionTreeLeaf(prediction);
			} else {
				interiorNode.right = new RegressionTreeLeaf(prediction);
			}
		}

		return tree;
	}