Skip to content

Commit

Permalink
Merge pull request #1375 from Dipanita45/DipaL
Browse files Browse the repository at this point in the history
Added the algorithm
  • Loading branch information
pankaj-bind authored Oct 30, 2024
2 parents 9b7cd77 + 3b86157 commit cb25291
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 0 deletions.
90 changes: 90 additions & 0 deletions Backtracking Algorithms/Leaf Similar Tree/Program_leaf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// Definition for a binary tree node.
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
};

// Function to create a new tree node
struct TreeNode* createNode(int val) {
struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));
newNode->val = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}

// Function to collect leaf nodes in the tree
void collectLeaves(struct TreeNode* root, int* leaves, int* index) {
if (root == NULL) {
return;
}
// If it's a leaf node, add its value to the leaves array
if (root->left == NULL && root->right == NULL) {
leaves[(*index)++] = root->val;
return;
}
// Recur for left and right subtrees
collectLeaves(root->left, leaves, index);
collectLeaves(root->right, leaves, index);
}

// Function to check if two trees are leaf-similar
bool leafSimilar(struct TreeNode* root1, struct TreeNode* root2) {
// Assuming a maximum of 100 leaves for simplicity
int leaves1[100], leaves2[100];
int index1 = 0, index2 = 0;

// Collect leaves of both trees
collectLeaves(root1, leaves1, &index1);
collectLeaves(root2, leaves2, &index2);

// Compare the number of leaves
if (index1 != index2) {
return false;
}

// Compare the leaf values
for (int i = 0; i < index1; i++) {
if (leaves1[i] != leaves2[i]) {
return false;
}
}

return true;
}

// Main function to test the leafSimilar function
int main() {
// Create first tree
struct TreeNode* root1 = createNode(3);
root1->left = createNode(5);
root1->right = createNode(1);
root1->left->left = createNode(6);
root1->left->right = createNode(2);
root1->left->right->left = createNode(9);
root1->left->right->right = createNode(4);

// Create second tree
struct TreeNode* root2 = createNode(7);
root2->left = createNode(2);
root2->right = createNode(1);
root2->left->left = createNode(6);
root2->left->right = createNode(5);

// Check if the trees are leaf-similar
if (leafSimilar(root1, root2)) {
printf("The trees are leaf-similar.\n");
} else {
printf("The trees are not leaf-similar.\n");
}

// Free allocated memory (not shown for brevity)
// You should implement a function to free the tree nodes.

return 0;
}
46 changes: 46 additions & 0 deletions Backtracking Algorithms/Leaf Similar Tree/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## Leaf-Similar Tree

# Problem Description
In the given problem, we are asked to compare two binary trees to check if they are 'leaf-similar'. Binary trees are a type of data structure in which each node has at most two children, referred to as the left child and the right child. A leaf node is a node with no children. The 'leaf value sequence' is the list of values of these leaf nodes read from left to right. Two binary trees are considered 'leaf-similar' if the sequences that of their leaf values are identical.

# Solution Approach
The solution is implemented in Python, and it focuses on a Depth-First Search (DFS) approach to traverse through the binary trees. The implementation defines a nested function dfs within the leafSimilar method, with the purpose of performing the actual DFS traversal, searching the entire tree for its leaves, and building the leaf sequence.

Here's the step-by-step breakdown of the algorithm:

The dfs function is defined, which takes a single argument, root, representing the current node in the tree.
Upon each invocation of dfs, the function first checks if the current root node is None. If it is, it returns an empty list as there are no leaves to gather from a None subtree.
If the current node is not None, the dfs function first recursively calls itself with root.left and root.right to search through the entire left and right subtrees.
The leaves are gathered by this part of the code: ans = dfs(root.left) + dfs(root.right). This code concatenates the left and right subtree leaves into one sequence.
Finally, the function checks if the node is a leaf node, that means both root.left and root.right are None. If it is a leaf, it returns a list containing the leaf's value: [root.val]. If the node is not a leaf, it returns the concatenated list of leaf values from both the left and right subtrees.
The main function leafSimilar calls the dfs function for both root1 and root2 trees, collecting the sequences of leaf values as lists.
The solution concludes by comparing these two lists with dfs(root1) == dfs(root2). If they are identical, it means that the leaf value sequences are the same, and therefore the two trees are considered leaf-similar and True is returned. If the sequences differ in any way, the function returns False.

# Examples:

Input: Roots of below Binary Trees
1
/ \
2 3
/ / \
4 6 7

0
/ \
5 8
\ / \
4 6 7
Output: same
Leaf order traversal of both trees is 4 6 7

Input: Roots of below Binary Trees
0
/ \
1 2
/ \
8 9

# Time Complexity and Space Complexity
The time complexity of the algorithm is determined by the depth-first search (DFS) function, which visits every node in the binary tree exactly once. Therefore, the time complexity is O(N+M), where N is the number of nodes in the first tree and M is the number of nodes in the second tree.

The space complexity is mainly governed by the call stack of the recursive DFS calls and the space used to store the leaf values. In the worst case, the depth of the recursion could be O(H1+H2), where H1 is the maximum height of the first tree and H2 is the maximum height of the second tree, if the trees are highly skewed.

0 comments on commit cb25291

Please sign in to comment.