Easy difficulty · Algorithm · Topics: tree, machine-learning, simulation
A decision tree predicts an answer by asking a sequence of yes/no questions about the input. Each internal node tests one feature against a threshold (humidity <= 75?), each branch is an answer to that test, and each leaf holds a prediction. Decision trees are among the most interpretable machine-learning models, and ensembles of them (random forests, gradient boosting such as XGBoost and LightGBM) are state of the art on tabular data. This sample evaluates a small hand-built "should we play tennis?" tree on a list of days and explains how such trees are learned.
It is the game of twenty questions. A good first question splits the possibilities into groups that are as "pure" as possible (mostly yes or mostly no); each later question refines one group. Prediction is a single walk from the root to a leaf, and the path itself explains the answer: "humidity was 85 (> 75) and temperature 30 (> 21), so no".
humidity <= 75 ?
/yes \no
wind <= 20 ? temp <= 21 ?
/yes \no /yes \no
"yes" "no" "yes" "no"
Prediction (what the code does)
value = day[node.feature]value <= node.thresholdlabel. playTennis repeats this for every day.Learning (how the splits would be chosen from data, e.g. CART or ID3/C4.5)
H = −Σ p_c · log2 p_c over classes c; information gain = H(parent) − weighted average H(children).G = 1 − Σ p_c², the chance of mislabeling a random row with a random label from the node. CART picks the split with the lowest weighted Gini.Example: 14 days with 9 "yes" and 5 "no" have entropy −(9/14)log2(9/14) − (5/14)log2(5/14) ≈ 0.940 bits. A split whose children are purer lowers the weighted entropy; the largest drop wins.
Case 0 evaluates four days (one per leaf):
day 1 {humidity 60, wind 10, temp 25}
humidity 60 <= 75 -> left; wind 10 <= 20 -> left leaf "yes"
day 2 {humidity 85, wind 5, temp 30}
humidity 85 > 75 -> right; temp 30 > 21 -> right leaf "no"
day 3 {humidity 70, wind 30, temp 18}
humidity 70 <= 75 -> left; wind 30 > 20 -> right leaf "no"
day 4 {humidity 90, wind 12, temp 18}
humidity 90 > 75 -> right; temp 18 <= 21 -> left leaf "yes"
answers = ["yes", "no", "no", "yes"]
| Task | Time | Space | Why |
|---|---|---|---|
| predict one input | O(depth) | O(1) | one comparison per level |
| predict m inputs | O(m · depth) | O(m) | one walk per input, answers stored |
| learn (CART, greedy) | O(f · n log n · depth) | O(n) | at each level, sort each of f features and scan thresholds over n rows |
value == threshold goes left (<=, as here) and use the same rule when learning and predicting.day[feature] is undefined, and undefined <= 75 is false, so the walk silently goes right. Validate inputs or learn a default direction.<=: encode categories properly or use multiway splits.tree is drawn as a binary tree: internal nodes are labelled with their feature, leaves with the answer.predict, node steps down one level per comparison; value shows the feature value being tested.answers fills with one label per day.Input: days = [
{ humidity: 60, wind: 10, temp: 25 },
{ humidity: 85, wind: 5, temp: 30 },
{ humidity: 70, wind: 30, temp: 18 },
{ humidity: 90, wind: 12, temp: 18 }
]
Output: ["yes", "no", "no", "yes"]
humidity (%), wind (km/h) and temp (°C).0 <= days.length <= 100function playTennis(days) {
const tree = buildPlayTennisTree();
const answers = [];
for (const day of days) {
answers.push(predict(tree, day));
}
return answers;
}
// Walks from the root to a leaf: left when day[feature] <= threshold, else right
function predict(tree, day) {
let node = tree;
while (node.label === undefined) {
const value = day[node.feature];
node = value <= node.threshold ? node.left : node.right;
}
return node.label;
}
// A small hand-built tree; a learning algorithm would choose these splits from data
function buildPlayTennisTree() {
const leaf = (label) => ({ label, left: null, right: null });
const split = (feature, threshold, left, right) => ({ feature, threshold, left, right });
return split(
"humidity", 75,
split("wind", 20, leaf("yes"), leaf("no")), // normal humidity: only wind matters
split("temp", 21, leaf("yes"), leaf("no")), // humid: fine when cool, not when hot
);
}