Binary tree- count number of nodes in a complete binary tree - recursion

I am to count number of nodes in a complete binary tree.I know one way to do this using recursion and my code looks like this
class Solution {
public:
int countNodes(TreeNode* root) {
if(!root)return 0;
int sz;
sz=1+countNodes(root->left)+countNodes(root->right);
return sz;
}
};
But it is giving me Time Limit Exceed in an online judge.Maybe in case of skewed binary tree.
How to do this more efficiently ?
P.S: I also tried BFS but no luck.

Related

Calculating number of nodes in BST using recursion c++

I'm trying to find the number of nodes in a BST using recursion. Here is my code
struct Node{
int key;
struct Node* left;
struct Node* right;
Node(){
int key = 0;
struct Node* left = nullptr;
struct Node* right = nullptr;
}
};
src_root is the address of the root node of the tree.
int BST::countNodes(Node* src_root, int sum){
if((src_root==root && src_root==nullptr) || src_root==nullptr)
return 0;
else if(src_root->left==nullptr || src_root->right==nullptr)
return sum;
return countNodes(src_root->left, sum + 1) + countNodes(src_root->right, sum + 1) + 1;
}
However my code only seems to work if there are 3 nodes. Anything greater than 3 gives wrong answer. Please help me find out what's wrong with it. Thanks!
It is a long time ago since I made anything in C/C++ so if there might be some syntax errors.
int BST::countNodes(Node *scr_root)
{
if (scr_root == null) return 0;
return 1 + countNodes(scr_root->left) + countNodes(scr_root->right);
}
I think that will do the job.
You have several logical and structural problems in your implementation. Casperah gave you the "clean" answer that I assume you already found on the web (if you haven't already done that research, you shouldn't have posted your question). Thus, what you're looking for is not someone else's solution, but how to fix your own.
Why do you pass sum down the tree? Lower nodes shouldn't care what the previous count is; it's the parent's job to accumulate the counts from its children. See how that's done in Casperah's answer? Drop the extra parameter from your code; it's merely another source for error.
Your base case has an identically false clause: src_root==root && src_root==nullptr ... if you make a meaningful call, src_root cannot be both root and nullptr.
Why are you comparing against a global value, root? Each call simply gets its own job done and returns. When your call tree crawls back to the original invocation, the one that was called with the root, it simply does its job and returns to the calling program. This should not be a special case.
Your else clause is wrong: it says that if either child is null, you ignore counting the other child altogether and return only the count so far. This guarantees that you'll give the wrong answer unless the tree is absolutely balanced and filled, a total of 2^N - 1 nodes for N levels.
Fix those items in whatever order you find instructive; the idea is to learn. Note, however, that your final code should look a lot like the answer Casperah provided.

Recursive Vs iterative Traversal of a BST

If I do recursive traversal of a binary tree of N nodes, it will occupy N spaces in execution stack.
If i use iteration , i will have to use N spaces in an explicit stack.
Question is do we say that recursive traversal is also using O(N) space complexity like iterative one is using?
I am talking in terms of running traversal code on some platform which bounds me by memory limits.
Also i am not talking of directly implementing iteration (in which one can say either of the approaches is fine), I am implementing algorithm for KthSmallestElement() in a BST which uses sort of traversal through the BST.
Should i use iterative approach or recursive approach in terms of space complexity, so that my code doesn't fail in space limits?
Putting it clearly:
Here is what i implemented:
int Solution::kthsmallest(TreeNode* root, int k) {
stack<TreeNode *> S;
while(1)
{
while(root)
{
S.push(root);
root=root->left;
}
root=S.top();
S.pop();
k--;
if(k==0)
return root->val;
root=root->right;
}
}
Here is what my friend implemented:
class Solution {
public:
int find(TreeNode* root, int &k) {
if (!root) return -1;
// We do an inorder traversal here.
int k1 = find(root->left, k);
if (k == 0) return k1; // left subtree has k or more elements.
k--;
if (k == 0) return root->val; // root is the kth element.
return find(root->right, k); // answer lies in the right node.
}
int kthsmallest(TreeNode* root, int k) {
return find(root, k); // Call another function to pass k by reference.
}
};
SO Which of the two is better & how?
If you care about memory use, you should try to ensure that your tree is balanced, i.e. that its depth is smaller than the number of nodes. A perfectly balanced binary tree with N nodes has depth log2N (rounded up).
It is important because the memory needed to visit all nodes in a binary tree is proportional to the depth of the tree, not to the number of nodes as you erroneously think; the recursive or iterative program needs to "remember" the path from the root to the current node, not other previously visited nodes.

what is the difference of these two implementations of a recursion algorihtm?

I am doing a leetcode problem.
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
How many possible unique paths are there?
So I tried this implementation first and got a "exceeds runtime" (I forgot the exact term but it means the implementation is slow). So I changed it version 2, which use a array to save the results. I honestly don't know how the recursion works internally and why these two implementations have different efficiency.
version 1(slow):
class Solution {
// int res[101][101]={{0}};
public:
int uniquePaths(int m, int n) {
if (m==1 || n==1) return 1;
else{
return uniquePaths(m-1,n) + uniquePaths(m,n-1);
}
}
};
version2 (faster):
class Solution {
int res[101][101]={{0}};
public:
int uniquePaths(int m, int n) {
if (m==1 || n==1) return 1;
else{
if (res[m-1][n]==0) res[m-1][n] = uniquePaths(m-1,n);
if (res[m][n-1]==0) res[m][n-1] = uniquePaths(m,n-1);
return res[m-1][n] + res[m][n-1];
}
}
};
Version 1 is slower beacuse you are calculating the same data again and again. I'll try to explain this on different problem but I guess that you know Fibonacci numbers. You can calculate any Fibonacci number by following recursive algorithm:
fib(n):
if n == 0 then return 0
if n == 1 then return 1
return fib(n-1) + fib(n-1)
But what actually are you calculating? If you want to find fib(5) you need to calculate fib(4) and fib(3), then to calculate fib(4) you need to calculate fib(3) again! Take a look at the image to fully understand:
The same situation is in your code. You compute uniquePaths(m,n) even if you have it calculated before. To avoid that, in your second version you use array to store computed data and you don't have to compute it again when res[m][n]!=0

Minimum number of jumps required to climb stairs

I recently had an interview with Microsoft for an internship and I was asked this question in the interview.
Its basically like, you have 2 parallel staircases and both the staircases have n steps. You start from the bottom and you may move upwards on either of the staircases. Each step on the staircase has a penalty attached to it.
You can also move across both the staircases with some other penalty.
I had to find the minimum penalty that will be imposed for reaching the top.
I tried writing a recurrence relation but I couldn't write anything because of so many variables.
I recently read about dynamic programming and I think this question is related to that.
With some googling, I found that this question is the same as
https://www.hackerrank.com/contests/frost-byte-final/challenges/stairway
Can you please give a solution or an approach for this problem ?
Create two arrays to keep track of the minimal cost to reach every position. Fill both arrays with huge numbers (e.g. 1000000000) and the start of the arrays with the cost of the first step.
Then iterate over all possible steps, and use an inner loop to iterate over all possible jumps.
foreach step in (0, N) {
// we're now sure we know minimal cost to reach this step
foreach jump in (1,K) {
// updating minimal costs here
}
}
Now every time we reach updating there are 4 possible moves to consider:
from A[step] to A[step+jump]
from A[step] to B[step+jump]
from B[step] to A[step+jump]
from B[step] to B[step+jump]
For each of these moves you need to compute the cost. Because you already know that you have the optimal cost to reach A[step] and B[step] this is easy. It's not guaranteed this new move is an improvement, so only update the target cost in your array if the new cost is lower then the cost already there.
Isn't this just a directed graph search? Any kind of simple pathfinding algorithm could handle this. See
https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
https://en.wikipedia.org/wiki/A*_search_algorithm
Just make sure you enforce the directional of the stairs (up only) and account for penalties (edge weights).
Worked solution
Of course, you could do it with dynamic programming, but I wouldn't be the one to ask for that...
import java.io.;
import java.util.;
public class Main {
public static int csmj(int []a,int src,int[] dp){
if(src>=a.length){
return Integer.MAX_VALUE-1;
}
if(src==a.length-1){
return 0;
}
if(dp[src]!=0){
return dp[src];
}
int count=Integer.MAX_VALUE-1;
for(int i=1;i<=a[src];i++){
count = Math.min( count , csmj(a,src+i,dp)+1 );
}
dp[src] = count;
return count;
}
public static void main(String args[] ) throws Exception {
Scanner s = new Scanner(System.in);
int n = s.nextInt();
int a[] = new int[n];
for(int i=0;i<n;i++){
a[i] = s.nextInt();
}
int minJumps = csmj(a,0,new int[n]);
System.out.println(minJumps);
}
}
bro you can have look at that solution my intuition is that

Connectivity of a Graph

int dfs(int graph[MAXNODES][MAXNODES],int visited[],int start) {
int stack[MAXNODES];
int top=-1,i;
visited[start]=1;
stack[++top]=start;
while(top!=-1)
{
start=stack[top];
for(i=0;i<MAXNODES;i++) {
if(graph[start][i]&&visited[i]==0) {
stack[++top]=i;
printf("%d-",i);
visited[i]=1;
break;
}
}
if(i==MAXNODES)
top--;
}
return 0;
}
The above code implements the dfs on a Graph stored as an Adjacency Matrix, I request a suggestion, what change should i be doing to know whether the generated graph is connected or not.
See my answer to an earlier question about strongly connected components.
Your dfs is also very inefficient as written, because you start over scanning at i=0 repeatedly; your stack should remember where you left off and continue from there. Recursion is more natural, but if you have bounded call stack size, then an explicit stack is best (for huge trees only).
Here's a recursive dfs. If you're not interested in storing the dfs tree, you can just store 1 in predecessor[] instead of the node you reached it from):
const unsigned MAXNODES=100;
/* predecessor must be 0-initialized by the caller; nodes graph[n] that are
reached from start will have predecessor[n]=p+1, where graph[pred] is the
predecessor via which n was reached from graph[start].
predecessor[start]=MAXNODES+1 (this is the root of the tree; there is NO
predecessor, but instead of 0, I put a positive value to show that it's
reached).
graph[a][b] is true iff there is a directed arc from a->b
*/
void dfs(bool graph[MAXNODES][MAXNODES],unsigned predecessor[]
,unsigned start,unsigned pred=MAXNODES)
{
if (predecessor[start]) return;
predecessor[start]=pred+1;
for (unsigned i=0;i<MAXNODES;++i)
if (graph[start][i])
dfs(graph,predecessor,i,start);
}
Here's a non-recursive dfs patterned on the above, but using the same stack variable for pred and i (in general you'd have a stack variable for every local variable and parameter that can change in your recursion):
void dfs_iter(bool graph[MAXNODES][MAXNODES],unsigned predecessor[]
,unsigned start)
{
unsigned stack[MAXNODES]; // node indices
unsigned n,pred;
int top=0;
stack[top]=start;
for(;;) {
recurse:
// invariant: stack[top] is the next (maybe reached) node
n=stack[top];
if (!predecessor[n]) { // not started yet
pred=top>0?stack[top-1]:MAXNODES;
//show(n,pred);
predecessor[n]=pred+1;
// the first thing we can reach from n
for (unsigned i=0;i<MAXNODES;++i)
if (graph[n][i] && !predecessor[i]) {
stack[++top]=i; goto recurse; // push
}
}
if (top>0) {
pred=stack[top-1];
// the next thing we can reach from pred after n
for (unsigned i=n+1;i<MAXNODES;++i)
if (graph[pred][i]) {
stack[top]=i; goto recurse; // replace top
}
--top;
} else
return;
}
}
This could be structured without the goto (it's just a named continue to the outmost loop), but without any more real clarity in my opinion.
Anyway, recursive calls are far simpler. There's recursive pseudocode for Tarjan's strongly connected components algorithm you can transcribe fairly directly. If you need help making it non-recursive (explicit stack), ask.
You'd need to store the edges generated by travelling from one node to the next. Then you could verify that all the nodes in the graph are connected by edges.
Run Dijkstra's algorithm. If at the end your queue is empty and some of the vertices aren't colored your graph isn't connected. This is guaranteed linear time, the dfs approach has a worst case analysis of quadratic.

Resources