[index|Home]] > Reflections | ⏮️ ⏭️
2024-07-04
🏋 Coding Practice
101. Symmetric Tree
Given the
root
of a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center).
🪞 Reflections
- This seems hard for an easy problem. Maybe I’m overlooking something…
- To be continued…
⌨️ My Solution
/* determine if a tree is symmatrical
Thoughts:
seems hard to recursively check for symmetry, since symmetry is judged from the root
Plan:
1. convert tree to levels
2. check if levels are symmetric
runtime complexity: O(N)
extra space complexity: O(N)
[4:13] Done planning
[10:00] Done with initial implementation
[15:15] Done with test
Bugs found after manual testing:
1. duplicate named function (isSymmetric)
2. didn't set default value for levels in treeToLevels helper
3. wrong answer: [1,2,2,null,3,null,3] -> true (expected false)
- I need to insert nulls into my levels to track their posiiton
- how do I do this without infinite looping with nulls?
- Easiest way seems to be checking the depth first
[27:18] Done adding depth check and adjusting code
next bugs found:
- missing else clause in ternaries in new depth function
- null pointer dereferencing in treeToLevels
- wrong answer: [1, 0] -> true (expected false)
- (falsey) zeros defaulted to null; add type check
[32:10] time limit exceeded
🤔 seems like filling out the entire tree takes too long
... we probably have degenerate skinny trees, so we're filling out exponentially more nodes than were provided
... we need a way to determine symmetry without having to build out the entire tree, filling in nodes
... but not right now. I thought this would be quick and now it's dinner time.
[43:26] To be continued...
*/
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function depth(root: TreeNode | null, max = 0): number {
if (!root) return max
const leftDepth: number = depth(root.left, max + 1)
const rightDepth: number = depth(root.right, max + 1)
return Math.max(leftDepth, rightDepth)
}
function treeToLevels(root: TreeNode | null, maxDepth: number, levels: (number | null)[][] = [], depth = 0): number[][] { // [1,2,3,4,2,4,3]
console.log('treeToLevels', {levels})
if (depth >= maxDepth) return levels
levels[depth] = (levels[depth] || []).concat(typeof root?.val === 'number' ? root.val : null) // [[1],[2, 2],[3,4,4,3]]
treeToLevels(root?.left || null, maxDepth, levels, depth + 1) // // //
treeToLevels(root?.right || null, maxDepth, levels, depth + 1) // // //
return levels
}
function isSymmetricArray(xs: (number | null)[]): boolean { // [3,4,4,3]; [2,2]; [1]
for (let l = 0, r = xs.length - 1; l <= r; l++, r--) {
if (xs[l] !== xs[r]) return false
}
return true // T; T; T
}
function isSymmetric(root: TreeNode | null): boolean { // [1,2,3,4,2,4,3]
if (!root) return true
const treeDepth = depth(root)
console.log({treeDepth})
const levels: number[][] = treeToLevels(root, treeDepth) // [[1],[2, 2],[3,4,4,3]]
console.log({levels})
return levels.every(isSymmetricArray) // T
};