An Even-Odd tree has specific constraints on each level: even-indexed levels must have strictly increasing odd values, while odd-indexed levels must have strictly decreasing even values. BFS naturally processes the tree level by level, making it ideal for checking these per-level conditions.
As we process each level, we track whether it is even or odd and verify that every node satisfies both the parity constraint (odd values on even levels, even values on odd levels) and the ordering constraint (increasing or decreasing based on level).
root and a boolean even = true to track the current level type.prev to negative infinity (for even levels) or positive infinity (for odd levels).prev.false.prev.even flag for the next level.true.# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isEvenOddTree(self, root: Optional[TreeNode]) -> bool:
even = True
q = deque([root])
while q:
prev = float("-inf") if even else float("inf")
for _ in range(len(q)):
node = q.popleft()
if even and (node.val % 2 == 0 or node.val <= prev):
return False
elif not even and (node.val % 2 == 1 or node.val >= prev):
return False
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
prev = node.val
even = not even
return TrueDFS can also solve this problem by tracking the last seen value at each level. As we traverse the tree in preorder (left to right), the first time we visit a level establishes the starting value. Subsequent visits to that level must satisfy the ordering constraint relative to the previous value we recorded.
We maintain an array where levels[i] stores the most recently seen value at level i. This lets us check ordering across a level even though DFS does not process levels sequentially.
levels array to track the last value seen at each depth.null, return true.false if not.levels[level]. Return false if violated, then update levels[level].level + 1.root at level 0.# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isEvenOddTree(self, root: Optional[TreeNode]) -> bool:
levels = []
def dfs(node, level):
if not node:
return True
even = level % 2 == 0
if ((even and node.val % 2 == 0) or
(not even and (node.val % 2 == 1))
):
return False
if len(levels) == level:
levels.append(node.val)
else:
if ((even and node.val <= levels[level]) or
(not even and node.val >= levels[level])
):
return False
levels[level] = node.val
return dfs(node.left, level + 1) and dfs(node.right, level + 1)
return dfs(root, 0)This approach mimics recursive DFS using an explicit stack, which can help avoid stack overflow for very deep trees. We store (node, level) pairs on the stack and process nodes in a similar order to recursive DFS.
The same levels array tracks the last seen value at each depth. By pushing the right child before the left child, we ensure left-to-right traversal order when popping.
(root, 0) and a levels array.(node, level) pair.false if violated.levels.levels[level]. Return false if violated.right child (if exists) then the left child (if exists) with level + 1.true.# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isEvenOddTree(self, root: Optional[TreeNode]) -> bool:
stack = [(root, 0)]
levels = []
while stack:
node, level = stack.pop()
even = level % 2 == 0
if ((even and node.val % 2 == 0) or
(not even and node.val % 2 == 1)
):
return False
if len(levels) == level:
levels.append(node.val)
else:
if ((even and node.val <= levels[level]) or
(not even and node.val >= levels[level])
):
return False
levels[level] = node.val
if node.right:
stack.append((node.right, level + 1))
if node.left:
stack.append((node.left, level + 1))
return TrueEven-indexed levels (0, 2, 4, ...) must have odd VALUES, while odd-indexed levels (1, 3, 5, ...) must have even VALUES. It is easy to mix these up and check if values match the level parity, which is the opposite of what the problem requires. Remember: level parity and value parity must be different.
The problem requires STRICTLY increasing order on even levels and STRICTLY decreasing order on odd levels. Using <= instead of < for increasing, or >= instead of > for decreasing, will incorrectly accept trees where adjacent nodes have equal values. Equal values at the same level should cause the function to return false.
When processing each level, the prev tracking variable must be reset to an appropriate initial value (negative infinity for even levels, positive infinity for odd levels). If you forget to reset it or initialize it incorrectly, comparisons with the first node of each level will fail, causing valid trees to be rejected or invalid trees to be accepted.