#import "@preview/cetz:0.3.1": canvas, draw #let leetcode-tree(nodes, highlighted: ()) = { let height = calc.ceil( calc.log( nodes.len() + 1, base: 2 ) ) let dy = 1 let dx = 0.8 let r = 0.3 let width = dx * (calc.pow(2, height - 1) + 1) for lvl in range(height) { let n = calc.pow(2, lvl) let y = -lvl * dy for i in range(n) { let j = i + n - 1 if j >= nodes.len() { break } let node = nodes.at(j) if node != none { let x = width * (i + .5) / n let name = "l" + str(lvl) + "-n" + str(i) let is-highlighted = (j in highlighted) or (lvl, i) in highlighted draw.circle( (x, y), radius: r, name: name, fill: if is-highlighted { blue.lighten(75%) } else { none } ) draw.content( name + ".center", str(node) ) if lvl != 0 { let pi = i.bit-rshift(1) draw.line( "l" + str(lvl - 1) + "-n" + str(pi), name ) } } } } } #set page(width: auto, height: auto, margin: 1cm) #canvas({ leetcode-tree( (2,1,3,none,none,none,4), highlighted: (2,) ) }) #pagebreak() #canvas({ leetcode-tree( (1,2,3,4,5,6,none,none,none,7,8) ) }) #pagebreak() #canvas({ leetcode-tree( (99,3,2,none,6,4,5,none,none,none,none,8,7) ) }) #pagebreak() #canvas({ leetcode-tree( (0,3,1,none,none,none,2) ) }) #pagebreak() #canvas({ leetcode-tree( (0,3,1,2) ) })