Solution code
const MATCH = 'match', MATCH_COLOR = 'green';
const VALUE_MATCH = 'value_match', VALUE_MATCH_COLOR = 'lightgreen';
const MISMATCH = 'mismatch', MISMATCH_COLOR = 'red';
const CURRENT = 'current', CURRENT_COLOR = 'blue';
function visMainFunction(pInput, qInput) {
initClassProperties();
const p = convertInputToTree(pInput);
const q = convertInputToTree(qInput);
startPartialBatch();
const treeP = new VisBinaryTree(p, { dataPropName: 'val' });
const treeQ = new VisBinaryTree(q, { dataPropName: 'val' });
explanationAndColorSchemaAndNotifications();
endBatch();
const result = isSameTree(p, q, treeP, treeQ);
if (result) {
notification(`✅ <b>The trees are the same.</b>`);
} else {
notification(`❌ <b>The trees are NOT the same.</b>`);
}
return result;
}
function isSameTree(p, q, treeP, treeQ) {
if (!p && !q) {
notification(`✅ Both nodes are <code>null</code> → match at this position.`);
return true;
}
startPartialBatch();
const vmP = p && treeP.makeVisManagerForNode(p);
const vmQ = q && treeQ.makeVisManagerForNode(q);
setAsCurrentNodes(p, q, treeP, treeQ);
if (!p || !q) {
handleMismatch(vmP, vmQ, `❌ Structural mismatch: one node is <code>null</code> and the other is not.`);
endBatch();
return false;
}
if (p.val !== q.val) {
handleMismatch(vmP, vmQ,`❌ Value mismatch at current pair: <b>${p.val}</b> vs <b>${q.val}</b>.`);
endBatch();
return false;
}
handleValueMatch(vmP, vmQ, `${makeColoredSpan('Values match', VALUE_MATCH_COLOR)} at ${makeColoredSpan('current pair', CURRENT_COLOR)}: <b>${p.val}</b> ✅ Proceeding to compare left children.`);
endBatch();
return isSameTree(p.left, q.left, treeP, treeQ) && handleLeftMatch(p, q, treeP, treeQ) && isSameTree(p.right, q.right, treeP, treeQ) && handleMatch(p, q, treeP, treeQ, vmP, vmQ);
}
let current1 = null, current2 = null;
function handleLeftMatch(node1, node2, tree1, tree2, message) {
startPartialBatch();
setAsCurrentNodes(node1, node2, tree1, tree2);
notification(`Left subtrees are same for ${makeColoredSpan('current pair', CURRENT_COLOR)}. ✅ Proceeding to compare right subtrees.`);
endBatch();
return true;
}
function handleMatch(node1, node2, tree1, tree2, visManager1, visManager2) {
startPartialBatch();
setAsCurrentNodes(node1, node2, tree1, tree2);
notification(`✅ Not just the values, but both left and right subtrees are the same for ${makeColoredSpan('current pair', CURRENT_COLOR)}, meaning these two nodes are ${makeColoredSpan('same', MATCH_COLOR)}.`);
startBatch();
visManager1.removeClass(VALUE_MATCH).addClass(MATCH);
visManager2.removeClass(VALUE_MATCH).addClass(MATCH);
endBatch();
endBatch();
return true;
}
function handleMismatch(visManager1, visManager2, message) {
notification(message);
startBatch();
visManager1?.addClass(MISMATCH);
visManager2?.addClass(MISMATCH);
endBatch();
}
function handleValueMatch(visManager1, visManager2, message) {
notification(message);
startBatch();
visManager1.addClass(VALUE_MATCH);
visManager2.addClass(VALUE_MATCH);
endBatch();
}
function setAsCurrentNodes(node1, node2, tree1, tree2) {
startBatch();
if (node1 !== current1) {
current1 && tree1.makeVisManagerForNode(current1).removeClass(CURRENT);
node1 && tree1.makeVisManagerForNode(node1).addClass(CURRENT);
current1 = node1;
}
if (node1 !== current2) {
current2 && tree2.makeVisManagerForNode(current2).removeClass(CURRENT);
node2 && tree2.makeVisManagerForNode(node2).addClass(CURRENT);
current2 = node2;
}
endBatch();
}
function initClassProperties() {
setClassProperties(MATCH, { backgroundColor: MATCH_COLOR });
setClassProperties(VALUE_MATCH, { backgroundColor: VALUE_MATCH_COLOR });
setClassProperties(MISMATCH, { backgroundColor: MISMATCH_COLOR });
setClassProperties(CURRENT, { borderColor: CURRENT_COLOR });
}
function convertInputToTree(arr) {
if (!arr.length || arr[0] === null) return null;
const nodes = arr.map(val => val === null ? null : new TreeNode(val));
for (let i = 0; i < nodes.length; i++) {
if (nodes[i]) {
nodes[i].left = nodes[2 * i + 1] || null;
nodes[i].right = nodes[2 * i + 2] || null;
}
}
return nodes[0];
}
function TreeNode(val, left = null, right = null) {
this.val = val;
this.left = left;
this.right = right;
}
function explanationAndColorSchemaAndNotifications() {
explanationNotification();
notification(`
🎨 <b>Visual Cues</b>
<ul>
<li>${makeColoredSpan('Current pair', CURRENT_COLOR)}: ${CURRENT_COLOR} border on the focused nodes in both trees</li>
<li>${makeColoredSpan('Value match', VALUE_MATCH_COLOR)}: ${VALUE_MATCH_COLOR} background (values equal at this level)</li>
<li>${makeColoredSpan('Full match', MATCH_COLOR)}: ${MATCH_COLOR} background (values equal <i>and</i> both left & right subtrees are same)</li>
<li>${makeColoredSpan('Mismatch', MISMATCH_COLOR)}: ${MISMATCH_COLOR} background (structure or value mismatch)</li>
</ul>
<small>
Nodes may first be marked ${makeColoredSpan('Value match', VALUE_MATCH_COLOR)} and later promoted to
${makeColoredSpan('Full match', MATCH_COLOR)} once both subtree checks succeed.
</small>
`);
}