Mastering Binary Trees and Sudoku: A Journey Through Depth and Logic in 90 Days


Introduction:
Welcome to Day 9 of my 90 Days DSA Challenge! Today, I focused on refining recursive logic and enhancing validation techniques. I tackled two essential binary tree problems using recursion and revisited the classic Valid Sudoku problem. This helped sharpen my understanding of tree depth analysis, path computation, and multidimensional constraint checking.
๐ณ Problem 1: Maximum Depth of Binary Tree (Bottom-Up Approach)
๐ Problem Statement:
Given the root of a binary tree, return its maximum depth. The depth is the number of nodes along the longest path from the root to a leaf.
๐ก Main Idea:
The idea is to determine the maximum depth by evaluating the longest path from root to any leaf node, using post-order recursion (i.e., process left and right before the current node).
โ Step-by-Step Approach:
If the current node is
null
, return 0.Recursively call the left and right subtree.
Get the depth from the left and right.
Take the maximum of both depths.
Add 1 to include the current node.
Return this value to the previous call.
๐ Code:
class Solution {
public int maxdepthhelper(TreeNode node){
if(node == null){
return 0;
}
int left = maxdepthhelper(node.left);
int right = maxdepthhelper(node.right);
return 1 + Math.max(left, right);
}
public int maxDepth(TreeNode root){
return maxdepthhelper(root);
}
}
๐ง Examples & Visuals:
Example 1:
1
/ \
2 3
Dry Run:
maxDepth(1) โ max( maxDepth(2), maxDepth(3) ) + 1
maxDepth(2) = 1 (leaf), maxDepth(3) = 1 (leaf)
Result = max(1,1)+1 = 2 โ
Example 2:
1
/
2
/
3
Dry Run:
maxDepth(1) โ maxDepth(2) + 1
maxDepth(2) โ maxDepth(3) + 1
maxDepth(3) = 1 (leaf)
Result = 1+1+1 = 3 โ
Example 3:
1
/ \
2 3
/ \
4 5
Dry Run:
Left path: 1 โ 2 โ 4 = depth 3
Right path: 1 โ 3 โ 5 = depth 3
max(3,3) = 3 โ
๐ฒ Problem 2: Path Sum
๐ Problem Statement:
Given a binary tree and a target sum, determine if there exists a root-to-leaf path such that the sum of the node values equals the given sum.
๐ก Main Idea:
Use pre-order traversal (root, left, right) to traverse paths while maintaining a running total of node values. Check if the total equals the target at each leaf.
โ Step-by-Step Approach:
Start at the root.
Add the current node's value to the running sum.
If you reach a leaf node, check if the running sum equals the target.
If it does, return true.
Otherwise, continue to left and right children.
If any path returns true, the overall result is true.
๐ Code:
class Solution {
public boolean preorderhelper(TreeNode node, int targetsum, int sum){
if(node == null){
return false;
}
sum += node.val;
if(node.left == null && node.right == null){
return sum == targetsum;
}
return preorderhelper(node.left, targetsum, sum) || preorderhelper(node.right, targetsum, sum);
}
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null){
return false;
}
return preorderhelper(root, targetSum, 0);
}
}
๐ง Examples & Visuals:
Example 1:
5
/ \
4 8
/ \
13 4
\
1
Target = 22
Dry Run:
Path 5โ4 = 9 โ
Path 5โ8โ13 = 26 โ
Path 5โ8โ4โ1 = 18 โ
No valid path found
Result: false โ
Example 2:
5
/ \
4 8
/ \
11 4
/ \
7 2
Target = 22
Dry Run:
Path 5โ4โ11โ2 = 5+4+11+2 = 22 โ
Result: true โ
Example 3:
1
/ \
2 3
Target = 5
Path 1โ2 = 3 โ
Path 1โ3 = 4 โ
No valid path
Result: false โ
๐ Problem 3: Valid Sudoku (Revised)
๐ Problem Statement:
Validate whether a 9x9 Sudoku board is valid. Only the filled cells need to be checked, not whether it is solvable.
๐ก Main Idea:
Track all values seen in each row, column, and box using separate matrices. If a duplicate is found in any, the board is invalid.
โ Step-by-Step Approach:
Traverse the board cell-by-cell.
Skip empty cells (denoted by '.').
Convert character to index (0-8).
Calculate box index using
3 * (r / 3) + (c / 3)
.Check if the value already exists in row, column, or box.
If found, return false. Else, mark as seen.
๐ Code:
class Solution {
public boolean isValidSudoku(char[][] board) {
int[][] rows = new int[9][9];
int[][] cols = new int[9][9];
int[][] boxes = new int[9][9];
for(int r = 0; r < 9; r++){
for(int c = 0; c < 9; c++){
if(board[r][c] == '.') continue;
int val = board[r][c] - '1';
int boxIdx = 3 * (r / 3) + (c / 3);
if(rows[r][val] == 1 || cols[c][val] == 1 || boxes[boxIdx][val] == 1){
return false;
}
rows[r][val] = 1;
cols[c][val] = 1;
boxes[boxIdx][val] = 1;
}
}
return true;
}
}
๐ง Examples & Visuals:
Example 1 (Valid):
5 3 . | . 7 . | . . .
6 . . | 1 9 5 | . . .
. 9 8 | . . . | . 6 .
------+-------+------
8 . . | . 6 . | . . 3
4 . . | 8 . 3 | . . 1
7 . . | . 2 . | . . 6
------+-------+------
. 6 . | . . . | 2 8 .
. . . | 4 1 9 | . . 5
. . . | . 8 . | . 7 9
Dry Run:
Traverse each row, column, and 3x3 box.
No duplicates found.
Result: true โ
Example 2 (Invalid due to row duplicate):
5 3 . | . 7 . | . . 5
...
Two 5's in the first row.
Result: false โ
Example 3 (Invalid due to box duplicate):
5 3 . | . 7 . | . . .
6 . . | 1 9 5 | . . .
. 9 5 | . . . | . 6 . โ duplicate '5' in top-left box
Duplicate detected in top-left 3x3 box
Result: false โ
๐งฉ Where I Got Stuck & How I Solved It
When I initially revisited the Valid Sudoku problem, I got stuck understanding how to uniquely identify each 3x3 box in the grid. I was using just the row and column index, which led to incorrect validations as I couldn't differentiate between boxes.
int val = board[3][3] - '1'; Letโs assume:
board[3][3] = '5' (a char, not an int)
'5' has an ASCII value of 53
'1' has an ASCII value of 49
So what happens:
java Copy Edit val = '5' - '1' = 53 - 49 = 4 ๐ค So we stored 4 โ how does that represent digit 5? Hereโs the magic: in zero-based arrays, we often use index = digit - 1 to map the digit to its correct array index.
Actual Digit Character ASCII Index Used (val) 1 '1' 49 0 2 '2' 50 1 3 '3' 51 2 4 '4' 52 3 5 '5' 53 4 โ ๐ก you are here! ... ... ... ... 9 '9' 57 8 ๐ So:
val = 4 โ represents digit 5
Thatโs why we store/check at rows[row][4] (for digit 5)
๐ง Think of val as: "the zero-based index for the digit stored as a character on the board"
So even though val = 4, it logically means digit 5, and you use it to index the array like this:
java Copy Edit rows[row][val] โ rows[3][4] โ means digit 5 used in row 3 cols[col][val] โ cols[3][4] โ means digit 5 used in column 3 boxes[box][val] โ boxes[4][4] โ means digit 5 used in box 4 โ Summary: Yes, val = 4
But that value is just the array index for digit 5
This is a very common and efficient trick to map characters '1'โ'9' to index 0โ8 in Sudoku and similar problems
๐ Line in question:
x = 3 * (r / 3) + (c / 3);
This formula gives a unique box index (0โ8) for each of the 9 sub-boxes in the 9ร9 Sudoku grid.
๐ง Visualize the Sudoku grid like this (divided into boxes):
+---+---+---+
| 0 | 1 | 2 |
+---+---+---+
| 3 | 4 | 5 |
+---+---+---+
| 6 | 7 | 8 |
+---+---+---+
Each 3ร3 block is numbered as above.
๐งฎ Box Index Formula Breakdown:
x = 3 * (r / 3) + (c / 3)
r / 3
โ tells you which row group (0, 1, or 2) the cell is inc / 3
โ tells you which column group (0, 1, or 2) the cell is in
Multiplying the row group by 3 and adding the column group gives you a unique box number from 0 to 8
โ Let's go through a few examples:
๐ธ Example 1: Cell (0, 0)
r = 0, c = 0
boxidx = 3 * (0 / 3) + (0 / 3) = 3 * 0 + 0 = 0
โ Belongs to top-left box (Box 0)
๐ธ Example 2: Cell (4, 5)
r = 4, c = 5
boxidx = 3 * (4 / 3) + (5 / 3) = 3 * 1 + 1 = 4
โ Belongs to center box (Box 4)
๐ธ Example 3: Cell (8, 8)
r = 8, c = 8
boxidx = 3 * (8 / 3) + (8 / 3) = 3 * 2 + 2 = 8
โ Belongs to bottom-right box (Box 8)
๐ธ Example 4: Cell (6, 2)
r = 6, c = 2
boxidx = 3 * (6 / 3) + (2 / 3) = 3 * 2 + 0 = 6
โ Belongs to bottom-left box (Box 6)
๐ฆ How it works in code:
if (boxes[boxidx][val] == 1) {
return false; // Digit already exists in this box
}
boxes[boxidx][val] = 1; // Mark digit as seen in this box
So youโre storing whether a digit has been seen before in the 3ร3 box using this computed index.
๐ง Takeaway:
You use
boxidx
to track digits inside a 3ร3 boxThe formula efficiently flattens a 2D 3ร3 grid into a 1D array of size 9
Conclusion:
Todayโs session reinforced essential concepts like recursive depth analysis, path validation, and constraint-based grid logic. Working with trees through both bottom-up and top-down approaches helped me appreciate the versatility of recursion. Meanwhile, revisiting Sudoku strengthened my ability to manage 2D arrays and logical conditions.
Onward to Day 10 with greater confidence and curiosity! ๐ช๐
#90DaysDSAChallenge #DSA #BinaryTrees #Recursion #Sudoku #Java #Algorithm #CodingChallenge #Learning
Subscribe to my newsletter
Read articles from Saivaishnav Ambati directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
