2313. Minimum Flips in Binary Tree to Get Result 🔒
Problem Description
You have a binary tree where each node contains a specific value with the following meaning:
Leaf nodes (nodes with no children):
- Value
0
representsfalse
- Value
1
representstrue
Non-leaf nodes (internal nodes) represent boolean operations:
- Value
2
representsOR
operation - Value
3
representsAND
operation - Value
4
representsXOR
operation - Value
5
representsNOT
operation
Special note: NOT
nodes have exactly one child (either left or right), while all other non-leaf nodes have exactly two children.
The tree evaluates to a boolean value following these rules:
- A leaf node evaluates to its boolean value (
0
→false
,1
→true
) - A non-leaf node evaluates by first evaluating its children, then applying its boolean operation to those child values
You can perform a "flip" operation on any leaf node, which changes:
0
(false) to1
(true)1
(true) to0
(false)
Given a binary tree root
and a target boolean value result
, find the minimum number of leaf flips needed to make the entire tree evaluate to result
.
For example, if you have an AND
node (value 3
) with two leaf children 1
and 0
, the tree evaluates to true AND false = false
. To make it evaluate to true
, you would need to flip the 0
leaf to 1
, requiring 1 flip operation.
The problem guarantees that it's always possible to achieve the desired result
through some combination of flips.
Flowchart Walkthrough
First, let's pin down the algorithm using the Flowchart. Here's a step-by-step walkthrough:
Is it a graph?
- Yes: While this problem involves a binary tree, a tree is a special type of graph (specifically, a connected acyclic graph). Binary trees are graphs with nodes connected by edges, where each node has at most two children.
Is it a tree?
- Yes: The problem explicitly states we're working with a binary tree. We have a root node, and each node can have up to two children (left and right). The tree structure is used to represent boolean expressions with operators at internal nodes and boolean values at leaf nodes.
DFS
- Yes: According to the flowchart, when we have a tree structure, DFS (Depth-First Search) is the recommended approach.
Conclusion: The flowchart suggests using DFS for this problem. This makes perfect sense because:
- We need to traverse the entire tree to evaluate boolean expressions
- We must compute values bottom-up (from leaves to root) to determine how each subtree evaluates
- At each node, we need to consider the minimum flips required to achieve both
true
andfalse
results - DFS allows us to recursively process each subtree and combine results at parent nodes based on the boolean operation
The DFS approach naturally handles the recursive nature of evaluating boolean expressions in a tree, where each non-leaf node's value depends on its children's evaluated values. We can use DFS to compute, for each node, the minimum flips needed to make that subtree evaluate to either true
or false
, then select the appropriate value based on the desired result.
Intuition
The key insight is that at any node in the tree, we need to know two pieces of information: how many flips are needed to make this subtree evaluate to false
, and how many flips are needed to make it evaluate to true
. Why both? Because the parent node might need either value depending on its operation and what result it's trying to achieve.
Think about it this way: if you're at an AND
node and want the result to be true
, you need both children to be true
. But if you're at an OR
node and want true
, you only need one child to be true
. So each child subtree should tell us: "It costs X flips to make me false
and Y flips to make me true
."
For leaf nodes, this is straightforward:
- If the leaf is
0
(false), it costs 0 flips to befalse
and 1 flip to betrue
- If the leaf is
1
(true), it costs 1 flip to befalse
and 0 flips to betrue
For non-leaf nodes, we combine the costs from children based on the boolean operation:
-
OR node (
2
): To getfalse
, both children must befalse
. To gettrue
, at least one child must betrue
(so we pick the cheapest option). -
AND node (
3
): To getfalse
, at least one child must befalse
(pick the cheapest). To gettrue
, both children must betrue
. -
XOR node (
4
): To getfalse
, children must have the same value (bothtrue
or bothfalse
). To gettrue
, children must differ. -
NOT node (
5
): Simply inverts the child - to getfalse
, we need the child to betrue
, and vice versa.
By computing both possibilities (cost to achieve false
and cost to achieve true
) at each node bottom-up, we can propagate this information to the root. At the root, we simply pick the cost corresponding to our desired result
.
This dynamic programming approach on the tree ensures we find the minimum number of flips by always choosing the cheapest option at each decision point while traversing from leaves to root.
Learn more about Tree, Depth-First Search, Dynamic Programming and Binary Tree patterns.
Solution Approach
The implementation uses tree dynamic programming with DFS to compute the minimum flips needed. We define a recursive function dfs(root)
that returns a tuple (cost_to_false, cost_to_true)
representing the minimum flips needed to make the subtree rooted at root
evaluate to false
and true
respectively.
Base Case:
- If the node is
None
, return(inf, inf)
since an empty tree can't be evaluated.
Leaf Nodes (values 0 or 1):
- For value
0
(false): return(0, 1)
- costs 0 flips to remainfalse
, 1 flip to becometrue
- For value
1
(true): return(1, 0)
- costs 1 flip to becomefalse
, 0 flips to remaintrue
- This is implemented as
return (x, x ^ 1)
wherex
is the node value
Non-Leaf Nodes: First, recursively compute costs for left and right children:
l, r = dfs(root.left), dfs(root.right)
Then handle each boolean operation:
-
OR Operation (value = 2):
- To get
false
: Both children must befalse
→l[0] + r[0]
- To get
true
: At least one child must betrue
→min(l[0] + r[1], l[1] + r[0], l[1] + r[1])
- To get
-
AND Operation (value = 3):
- To get
false
: At least one child must befalse
→min(l[0] + r[0], l[0] + r[1], l[1] + r[0])
- To get
true
: Both children must betrue
→l[1] + r[1]
- To get
-
XOR Operation (value = 4):
- To get
false
: Children must have same value →min(l[0] + r[0], l[1] + r[1])
- To get
true
: Children must have different values →min(l[0] + r[1], l[1] + r[0])
- To get
-
NOT Operation (value = 5):
- To get
false
: Child must betrue
→min(l[1], r[1])
(only one child exists) - To get
true
: Child must befalse
→min(l[0], r[0])
- To get
Final Result:
After computing the costs for the root, we return dfs(root)[int(result)]
:
- If
result
isFalse
, we needdfs(root)[0]
- If
result
isTrue
, we needdfs(root)[1]
The time complexity is O(n)
where n
is the number of nodes, as we visit each node once. The space complexity is O(h)
where h
is the height of the tree, due to the recursion stack.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a small example to illustrate the solution approach.
Consider this binary tree where we want the result to be True
:
AND (3) / \ OR (2) true (1) / \ false(0) true(1)
We'll compute the costs bottom-up using DFS.
Step 1: Process the leftmost leaf false (0)
- Cost to make it false: 0 flips (already false)
- Cost to make it true: 1 flip
- Returns:
(0, 1)
Step 2: Process the middle leaf true (1)
- Cost to make it false: 1 flip
- Cost to make it true: 0 flips (already true)
- Returns:
(1, 0)
Step 3: Process the OR node (2)
- Left child costs:
(0, 1)
- Right child costs:
(1, 0)
- For OR to be false: both children must be false →
0 + 1 = 1
flip - For OR to be true: at least one child must be true →
min(0+0, 1+1, 1+0) = 0
flips - Returns:
(1, 0)
Step 4: Process the rightmost leaf true (1)
- Cost to make it false: 1 flip
- Cost to make it true: 0 flips
- Returns:
(1, 0)
Step 5: Process the root AND node (3)
- Left child (OR) costs:
(1, 0)
- Right child costs:
(1, 0)
- For AND to be false: at least one child must be false →
min(1+1, 1+0, 0+1) = 1
flip - For AND to be true: both children must be true →
0 + 0 = 0
flips - Returns:
(1, 0)
Final Result:
Since we want the tree to evaluate to True
, we look at index 1 of the root's result: 0
flips needed.
This makes sense: the OR node already evaluates to true (false OR true = true), and the rightmost leaf is already true, so true AND true = true with no flips needed!
If we wanted the result to be False
instead, we'd need 1 flip (either flip the middle leaf from true to false, making the OR evaluate to false, or flip the rightmost leaf from true to false).
Solution Implementation
1# Definition for a binary tree node.
2# class TreeNode:
3# def __init__(self, val=0, left=None, right=None):
4# self.val = val
5# self.left = left
6# self.right = right
7
8from typing import Optional, Tuple
9from math import inf
10
11class Solution:
12 def minimumFlips(self, root: Optional[TreeNode], result: bool) -> int:
13 def dfs(node: Optional[TreeNode]) -> Tuple[int, int]:
14 """
15 Returns a tuple (cost_to_make_false, cost_to_make_true) for the subtree.
16
17 Args:
18 node: Current tree node
19
20 Returns:
21 Tuple containing minimum flips needed to make subtree evaluate to:
22 - [0]: False
23 - [1]: True
24 """
25 # Base case: empty node
26 if node is None:
27 return inf, inf
28
29 node_value = node.val
30
31 # Leaf nodes: value is 0 or 1
32 if node_value in (0, 1):
33 # Cost to keep current value is 0, cost to flip is 1
34 return node_value, node_value ^ 1
35
36 # Recursively calculate costs for left and right subtrees
37 left_costs, right_costs = dfs(node.left), dfs(node.right)
38
39 # OR operation (value = 2)
40 if node_value == 2:
41 # To get False: both children must be False
42 cost_to_false = left_costs[0] + right_costs[0]
43 # To get True: at least one child must be True
44 cost_to_true = min(
45 left_costs[0] + right_costs[1], # Left False, Right True
46 left_costs[1] + right_costs[0], # Left True, Right False
47 left_costs[1] + right_costs[1] # Both True
48 )
49 return cost_to_false, cost_to_true
50
51 # AND operation (value = 3)
52 if node_value == 3:
53 # To get False: at least one child must be False
54 cost_to_false = min(
55 left_costs[0] + right_costs[0], # Both False
56 left_costs[0] + right_costs[1], # Left False, Right True
57 left_costs[1] + right_costs[0] # Left True, Right False
58 )
59 # To get True: both children must be True
60 cost_to_true = left_costs[1] + right_costs[1]
61 return cost_to_false, cost_to_true
62
63 # XOR operation (value = 4)
64 if node_value == 4:
65 # To get False: both children must have same value
66 cost_to_false = min(
67 left_costs[0] + right_costs[0], # Both False
68 left_costs[1] + right_costs[1] # Both True
69 )
70 # To get True: children must have different values
71 cost_to_true = min(
72 left_costs[0] + right_costs[1], # Left False, Right True
73 left_costs[1] + right_costs[0] # Left True, Right False
74 )
75 return cost_to_false, cost_to_true
76
77 # NOT operation (value = 5)
78 # Only has one child (could be left or right)
79 # To get False: child must be True
80 cost_to_false = min(left_costs[1], right_costs[1])
81 # To get True: child must be False
82 cost_to_true = min(left_costs[0], right_costs[0])
83 return cost_to_false, cost_to_true
84
85 # Get the minimum flips for the entire tree
86 # Index 0 for False, 1 for True
87 return dfs(root)[int(result)]
88
1/**
2 * Definition for a binary tree node.
3 * public class TreeNode {
4 * int val;
5 * TreeNode left;
6 * TreeNode right;
7 * TreeNode() {}
8 * TreeNode(int val) { this.val = val; }
9 * TreeNode(int val, TreeNode left, TreeNode right) {
10 * this.val = val;
11 * this.left = left;
12 * this.right = right;
13 * }
14 * }
15 */
16class Solution {
17 /**
18 * Finds the minimum number of flips needed to make the tree evaluate to the target result.
19 * @param root The root of the binary tree
20 * @param result The target boolean result we want to achieve
21 * @return Minimum number of flips required
22 */
23 public int minimumFlips(TreeNode root, boolean result) {
24 // Get minimum flips for both false and true results
25 int[] minFlips = dfs(root);
26 // Return the minimum flips for the desired result
27 return result ? minFlips[1] : minFlips[0];
28 }
29
30 /**
31 * Performs DFS to calculate minimum flips needed for both false and true results.
32 * @param root Current node in the tree
33 * @return Array where index 0 = min flips for false, index 1 = min flips for true
34 */
35 private int[] dfs(TreeNode root) {
36 // Base case: null node (shouldn't happen in valid tree)
37 if (root == null) {
38 return new int[] {1 << 30, 1 << 30}; // Return large values as infinity
39 }
40
41 int nodeValue = root.val;
42
43 // Leaf node: value is 0 or 1
44 if (nodeValue < 2) {
45 // For value 0: 0 flips to get false, 1 flip to get true
46 // For value 1: 1 flip to get false, 0 flips to get true
47 return new int[] {nodeValue, nodeValue ^ 1};
48 }
49
50 // Recursively get minimum flips for left and right subtrees
51 int[] leftMinFlips = dfs(root.left);
52 int[] rightMinFlips = dfs(root.right);
53
54 // Initialize minimum flips for false and true results
55 int minFlipsForFalse = 0;
56 int minFlipsForTrue = 0;
57
58 // OR operation (value = 2)
59 if (nodeValue == 2) {
60 // For false result: both children must be false
61 minFlipsForFalse = leftMinFlips[0] + rightMinFlips[0];
62 // For true result: at least one child must be true
63 minFlipsForTrue = Math.min(
64 leftMinFlips[0] + rightMinFlips[1], // Left false, right true
65 Math.min(
66 leftMinFlips[1] + rightMinFlips[0], // Left true, right false
67 leftMinFlips[1] + rightMinFlips[1] // Both true
68 )
69 );
70 }
71 // AND operation (value = 3)
72 else if (nodeValue == 3) {
73 // For false result: at least one child must be false
74 minFlipsForFalse = Math.min(
75 leftMinFlips[0] + rightMinFlips[0], // Both false
76 Math.min(
77 leftMinFlips[0] + rightMinFlips[1], // Left false, right true
78 leftMinFlips[1] + rightMinFlips[0] // Left true, right false
79 )
80 );
81 // For true result: both children must be true
82 minFlipsForTrue = leftMinFlips[1] + rightMinFlips[1];
83 }
84 // XOR operation (value = 4)
85 else if (nodeValue == 4) {
86 // For false result: both children must have same value
87 minFlipsForFalse = Math.min(
88 leftMinFlips[0] + rightMinFlips[0], // Both false
89 leftMinFlips[1] + rightMinFlips[1] // Both true
90 );
91 // For true result: children must have different values
92 minFlipsForTrue = Math.min(
93 leftMinFlips[0] + rightMinFlips[1], // Left false, right true
94 leftMinFlips[1] + rightMinFlips[0] // Left true, right false
95 );
96 }
97 // NOT operation (value = 5)
98 else {
99 // For false result: child must be true (ignores one child)
100 minFlipsForFalse = Math.min(leftMinFlips[1], rightMinFlips[1]);
101 // For true result: child must be false (ignores one child)
102 minFlipsForTrue = Math.min(leftMinFlips[0], rightMinFlips[0]);
103 }
104
105 return new int[] {minFlipsForFalse, minFlipsForTrue};
106 }
107}
108
1/**
2 * Definition for a binary tree node.
3 * struct TreeNode {
4 * int val;
5 * TreeNode *left;
6 * TreeNode *right;
7 * TreeNode() : val(0), left(nullptr), right(nullptr) {}
8 * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
9 * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
10 * };
11 */
12class Solution {
13public:
14 int minimumFlips(TreeNode* root, bool result) {
15 // Lambda function to recursively calculate minimum flips
16 // Returns pair<min_flips_for_false, min_flips_for_true>
17 function<pair<int, int>(TreeNode*)> dfs = [&](TreeNode* node) -> pair<int, int> {
18 // Base case: null node returns infinity for both states
19 if (!node) {
20 return {1 << 30, 1 << 30};
21 }
22
23 int nodeValue = node->val;
24
25 // Leaf nodes: values 0 (false) or 1 (true)
26 if (nodeValue < 2) {
27 // For leaf nodes, cost to achieve false/true
28 // nodeValue=0: {0, 1} (0 flips for false, 1 flip for true)
29 // nodeValue=1: {1, 0} (1 flip for false, 0 flips for true)
30 return {nodeValue, nodeValue ^ 1};
31 }
32
33 // Recursively get minimum flips for left and right subtrees
34 auto [leftFalse, leftTrue] = dfs(node->left);
35 auto [rightFalse, rightTrue] = dfs(node->right);
36
37 int minFlipsForFalse = 0;
38 int minFlipsForTrue = 0;
39
40 // Handle different operator types
41 if (nodeValue == 2) { // OR operator
42 // OR is false only when both children are false
43 minFlipsForFalse = leftFalse + rightFalse;
44 // OR is true when at least one child is true
45 minFlipsForTrue = min({leftFalse + rightTrue,
46 leftTrue + rightFalse,
47 leftTrue + rightTrue});
48 }
49 else if (nodeValue == 3) { // AND operator
50 // AND is false when at least one child is false
51 minFlipsForFalse = min({leftFalse + rightFalse,
52 leftFalse + rightTrue,
53 leftTrue + rightFalse});
54 // AND is true only when both children are true
55 minFlipsForTrue = leftTrue + rightTrue;
56 }
57 else if (nodeValue == 4) { // XOR operator
58 // XOR is false when both children have same value
59 minFlipsForFalse = min(leftFalse + rightFalse,
60 leftTrue + rightTrue);
61 // XOR is true when children have different values
62 minFlipsForTrue = min(leftFalse + rightTrue,
63 leftTrue + rightFalse);
64 }
65 else { // nodeValue == 5: NOT operator (unary, uses only one child)
66 // NOT inverts the child's value
67 // To make NOT false, we need child to be true
68 minFlipsForFalse = min(leftTrue, rightTrue);
69 // To make NOT true, we need child to be false
70 minFlipsForTrue = min(leftFalse, rightFalse);
71 }
72
73 return {minFlipsForFalse, minFlipsForTrue};
74 };
75
76 // Get minimum flips for both false and true results
77 auto [flipsForFalse, flipsForTrue] = dfs(root);
78
79 // Return based on desired result
80 return result ? flipsForTrue : flipsForFalse;
81 }
82};
83
1/**
2 * Definition for a binary tree node.
3 * class TreeNode {
4 * val: number
5 * left: TreeNode | null
6 * right: TreeNode | null
7 * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
8 * this.val = (val===undefined ? 0 : val)
9 * this.left = (left===undefined ? null : left)
10 * this.right = (right===undefined ? null : right)
11 * }
12 * }
13 */
14
15/**
16 * Calculates the minimum number of flips needed to make the binary tree evaluate to the target result
17 * @param root - The root node of the binary expression tree
18 * @param result - The target boolean result (true or false)
19 * @returns The minimum number of flips required
20 */
21function minimumFlips(root: TreeNode | null, result: boolean): number {
22 // Helper function that returns [minFlipsForFalse, minFlipsForTrue]
23 const calculateMinFlips = (node: TreeNode | null): [number, number] => {
24 // Base case: if node is null, return large values as placeholders
25 if (!node) {
26 return [1 << 30, 1 << 30];
27 }
28
29 const nodeValue = node.val;
30
31 // Leaf nodes: values 0 (false) or 1 (true)
32 if (nodeValue < 2) {
33 // For leaf nodes, cost to get the value is 0, cost to flip is 1
34 return [nodeValue, nodeValue ^ 1];
35 }
36
37 // Recursively calculate min flips for left and right subtrees
38 const [leftFalseFlips, leftTrueFlips] = calculateMinFlips(node.left);
39 const [rightFalseFlips, rightTrueFlips] = calculateMinFlips(node.right);
40
41 // Handle different operators
42 if (nodeValue === 2) {
43 // OR operator: false when both are false, true otherwise
44 return [
45 leftFalseFlips + rightFalseFlips,
46 Math.min(
47 leftFalseFlips + rightTrueFlips,
48 leftTrueFlips + rightFalseFlips,
49 leftTrueFlips + rightTrueFlips
50 )
51 ];
52 }
53
54 if (nodeValue === 3) {
55 // AND operator: true when both are true, false otherwise
56 return [
57 Math.min(
58 leftFalseFlips + rightFalseFlips,
59 leftFalseFlips + rightTrueFlips,
60 leftTrueFlips + rightFalseFlips
61 ),
62 leftTrueFlips + rightTrueFlips
63 ];
64 }
65
66 if (nodeValue === 4) {
67 // XOR operator: true when values differ, false when same
68 return [
69 Math.min(
70 leftFalseFlips + rightFalseFlips,
71 leftTrueFlips + rightTrueFlips
72 ),
73 Math.min(
74 leftFalseFlips + rightTrueFlips,
75 leftTrueFlips + rightFalseFlips
76 )
77 ];
78 }
79
80 // NOT operator (nodeValue === 5): inverts the child's value
81 // Note: NOT operator only has left child in this problem
82 return [
83 Math.min(leftTrueFlips, rightTrueFlips),
84 Math.min(leftFalseFlips, rightFalseFlips)
85 ];
86 };
87
88 // Get the minimum flips for both false and true results
89 const [minFlipsForFalse, minFlipsForTrue] = calculateMinFlips(root);
90
91 // Return the minimum flips based on the desired result
92 return result ? minFlipsForTrue : minFlipsForFalse;
93}
94
Time and Space Complexity
Time Complexity: O(n)
The algorithm performs a depth-first search (DFS) traversal of the binary tree. Each node is visited exactly once during the traversal. At each node, the function performs constant time operations:
- For leaf nodes (values 0 or 1), it returns values in
O(1)
time - For internal nodes (values 2, 3, 4, or 5), it performs constant time calculations using the results from child nodes
Since we visit all n
nodes exactly once and perform O(1)
work at each node, the total time complexity is O(n)
.
Space Complexity: O(n)
The space complexity comes from the recursive call stack used during the DFS traversal. In the worst case, when the tree is completely unbalanced (essentially a linked list), the recursion depth can be O(n)
. In the best case of a balanced tree, the recursion depth would be O(log n)
. However, considering the worst-case scenario, the space complexity is O(n)
.
Additionally, each recursive call stores a constant amount of data (the return values and local variables), which doesn't change the overall space complexity of O(n)
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Handling of NOT Operation's Single Child
Pitfall: A common mistake is assuming that NOT nodes always have their child in a specific position (either left or right). Developers often write code like:
# WRONG: Assumes child is always on the left if node_value == 5: cost_to_false = left_costs[1] cost_to_true = left_costs[0]
Problem: If the NOT node's only child is on the right side, left_costs
would be (inf, inf)
, leading to incorrect results.
Solution: Use min()
to handle both possibilities:
# CORRECT: Handles child on either side
if node_value == 5:
cost_to_false = min(left_costs[1], right_costs[1])
cost_to_true = min(left_costs[0], right_costs[0])
2. Forgetting to Consider All Combinations for OR/AND Operations
Pitfall: When calculating the minimum cost for OR to evaluate to true (or AND to evaluate to false), developers might forget some valid combinations:
# WRONG: Missing the case where both children are true
if node_value == 2: # OR
cost_to_true = min(
left_costs[0] + right_costs[1],
left_costs[1] + right_costs[0]
) # Missing: left_costs[1] + right_costs[1]
Problem: This misses valid scenarios and may return a suboptimal answer.
Solution: Include all valid combinations:
# CORRECT: Includes all cases where OR evaluates to true
cost_to_true = min(
left_costs[0] + right_costs[1], # F OR T = T
left_costs[1] + right_costs[0], # T OR F = T
left_costs[1] + right_costs[1] # T OR T = T
)
3. Confusing Leaf Node Return Values
Pitfall: Incorrectly calculating the flip costs for leaf nodes:
# WRONG: Reversed logic if node_value in (0, 1): return 1 - node_value, node_value # Incorrect!
Problem: This reverses the costs - a node with value 0 would return (1, 0) instead of (0, 1).
Solution: Remember that the tuple represents (cost_to_make_false, cost_to_make_true)
:
# CORRECT: For a leaf with value x # - Cost to make it false: x (flip if it's 1, don't flip if it's 0) # - Cost to make it true: x^1 (flip if it's 0, don't flip if it's 1) return node_value, node_value ^ 1
4. Not Handling Empty/None Nodes Properly
Pitfall: Returning incorrect values for None nodes or not handling them at all:
# WRONG: Returns 0 costs for None nodes if node is None: return 0, 0
Problem: This would incorrectly allow operations on non-existent children, producing wrong results.
Solution: Return infinity to indicate impossibility:
# CORRECT: None nodes can't be evaluated if node is None: return inf, inf
This ensures that when min()
is used with NOT operations, only the existing child's cost is considered.
Which two pointer techniques do you use to check if a string is a palindrome?
Recommended Readings
Everything About Trees A tree is a type of graph data structure composed of nodes and edges Its main properties are It is acyclic doesn't contain any cycles There exists a path from the root to any node Has N 1 edges where N is the number of nodes in the tree and
https assets algo monster cover_photos dfs svg Depth First Search Prereqs Recursion Review problems recursion_intro Trees problems tree_intro With a solid understanding of recursion under our belts we are now ready to tackle one of the most useful techniques in coding interviews Depth First Search DFS As the name suggests
What is Dynamic Programming Prerequisite DFS problems dfs_intro Backtracking problems backtracking Memoization problems memoization_intro Pruning problems backtracking_pruning Dynamic programming is an algorithmic optimization technique that breaks down a complicated problem into smaller overlapping sub problems in a recursive manner and uses solutions to the sub problems to construct a solution
Want a Structured Path to Master System Design Too? Don’t Miss This!