Subtrees of height h in Binary tree - recursion

How do we find number of subtrees of height 'h' in a binary tree.
Function is defined as
int subtree( node *root, int k);
where k is the specific height.

First, we recursively calculate the height of the tree as follows:
If the tree is empty, the height is 0.
If the tree is non-empty, the height is the maximum height of its children, plus 1.
In C (I assume OP is using C based on response), this looks like
typedef struct Node {
Node* leftChild,
node* rightChild
} Node;
typedef Node* Tree;
unsigned int max(unsigned int a, unsigned int b) {
return a > b ? a : b;
}
unsigned int height(Tree tree) {
return tree ? 1 + max(height(tree->leftChild, tree->rightChild)) : 0;
}
Note that generally, Node will have some additional data. But that data isn't relevant here, so we don't include it (although it's easy enough to do so if you wish to).
Now, we want to modify the height function slightly. To do this, we define
typdef struct Result {
unsigned int height,
unsigned int count
} Result;
/**
* The returned .height should be the height of the tree.
* The returned .count should be the number of subtrees of tree
* with height k.
*/
Result resultCountChildren(Tree tree, unsigned int k) {
if (tree) {
Result leftResult = resultCountChildren(tree->left, k);
Result rightResult = resultCountChildren(tree->right, k);
unsigned int heightOfTree = 1 + max(leftResult.height, rightResult.height);
unsigned int count = leftResult.count + rightResult.count + (heightOfTree == k);
Result result = {
.height = heightOfTree,
.count = count
};
return result;
} else {
unsigned int height = 0;
unsigned int count = (0 == k);
Result result = {
.height = height,
.count = count
};
return result;
}
}
unsigned int count(Tree tree, unsigned int k) {
return resultCountChildren(tree).count;
}

Related

lowest common ancestor in binary tree (strange behaviour of recursive function)

Here's the code which I submitted on gfg and it worked perfectly fine. But I can't figure out how it is working even when its not returning anything. How the variable 'avail' is becoming '-2' in any recursive call becoz the function is not returning anything.
/* A binary tree node
struct Node
{
int data;
struct Node* left;
struct Node* right;
Node(int x){
data = x;
left = right = NULL;
}
};
*/
class Solution
{
public:
// Function to return the lowest common ancestor in a Binary Tree.
int recursion(Node *p, int a, int b, Node *&answer)
{
if (p == nullptr)
return 0;
int avail;
if (p->data == a or p->data == b)
{
avail = -1;
avail = recursion(p->left, a, b, answer) + recursion(p->right, a, b, answer) + (-1);
}
else
avail = recursion(p->left, a, b, answer) + recursion(p->right, a, b, answer);
if (avail == -2)
{
answer = p;
}
// return 1;
}
Node *lca(Node *root, int n1, int n2)
{
Node *answer;
recursion(root, n1, n2, answer);
return answer;
}
};

Why Complete LinkedList Reversed?

For Input 1->2->2->4->5->6->7->8
My output is 8 7 6 5 4 2 2 1 but I don't know why?
LINK OF PROBLEM IS BELOW :
https://practice.geeksforgeeks.org/problems/reverse-a-linked-list-in-groups-of-given-size/1
Reverse a Linked List in groups of given size.
Given a linked list of size N. The task is to reverse every k nodes (where k is an input to the function) in the linked list. If the number of nodes is not a multiple of k then left-out nodes, in the end, should be considered as a group and must be reversed (See Example 2 for clarification).
Example 1:
Input:
LinkedList: 1->2->2->4->5->6->7->8
K = 4
Output: 4 2 2 1 8 7 6 5
Explanation:
The first 4 elements 1,2,2,4 are reversed first
and then the next 4 elements 5,6,7,8. Hence, the
resultant linked list is 4->2->2->1->8->7->6->5.
Example 2:
Input:
LinkedList: 1->2->3->4->5
K = 3
Output: 3 2 1 5 4
Explanation:
The first 3 elements are 1,2,3 are reversed
first and then elements 4,5 are reversed.Hence,
the resultant linked list is 3->2->1->5->4.
Your Task:
You don't need to read input or print anything. Your task is to complete the function reverse() which should reverse the linked list in group of size k and return the head of the modified linked list.
Expected Time Complexity : O(N)
Expected Auxilliary Space : O(1)
Constraints:
1 <= N <= 104
1 <= k <= N
MY CODE BELOW:
//{ Driver Code Starts
#include<bits/stdc++.h>
using namespace std;
struct node
{
int data;
struct node* next;
node(int x){
data = x;
next = NULL;
}
};
/* Function to print linked list */
void printList(struct node *node)
{
while (node != NULL)
{
printf("%d ", node->data);
node = node->next;
}
printf("\n");
}
// } Driver Code Ends
/*
Reverse a linked list
The input list will have at least one element
Return the node which points to the head of the new LinkedList
Node is defined as
struct node
{
int data;
struct node* next;
node(int x){
data = x;
next = NULL;
}
}*head;
*/
class Solution
{
node* reverseHelper(node* head){
node* pre = NULL;
node* curr = head;
while(curr!=NULL){
node* nextTocurr = curr->next;
curr->next = pre;
pre = curr;
curr = nextTocurr;
}
return pre;
}
public:
struct node *reverse (struct node *head, int k)
{
// Complete this method
if(head==NULL|| head->next==NULL){
return head;
}
int count = 0;
node* tail = head;
while(count<k || tail->next!=NULL){
tail = tail->next;
count++;
}
node* head2 = tail->next;
tail->next = NULL;
node* ans = reverseHelper(head);
head->next = reverse(head2,k);
return ans;
}
};
//{ Driver Code Starts.
/* Drier program to test above function*/
int main(void)
{
int t;
cin>>t;
while(t--)
{
struct node* head = NULL;
struct node* temp = NULL;
int n;
cin >> n;
for(int i=0 ; i<n ; i++)
{
int value;
cin >> value;
if(i == 0)
{
head = new node(value);
temp = head;
}
else
{
temp->next = new node(value);
temp = temp->next;
}
}
int k;
cin>>k;
Solution ob;
head = ob.reverse(head, k);
printList(head);
}
return(0);
}
// } Driver Code Ends
The problem is in this loop:
int count = 0;
while(count<k || tail->next!=NULL){
It has two issues:
The loop will continue until the end of the list because the second condition will be true until that end is reached. The logical OR (||) should be a logical AND (&&), because you want both conditions to be true, not just one.
When the previous point is corrected, the loop will still iterate one time too many, because the head node was already considered to be included in the "slice". Correct by initialising count=1.
With those two corrections your code will work as intended.

Frama-C slice: parallelizable loop

I am trying to perform a backward slicing of an array element at specific position. I tried two different source codes. The first one is (first.c):
const int in_array[5][5]={
1,2,3,4,5,
6,7,8,9,10,
11,12,13,14,15,
16,17,18,19,20,
21,22,23,24,25
};
int out_array[5][5];
int main(unsigned int x, unsigned int y)
{
int res;
int i;
int j;
for(i=0; i<5; i++){
for(j=0; j<5; j++){
out_array[i][j]=i*j*in_array[i][j];
}
}
res = out_array[x][y];
return res;
}
I run the command:
frama-c-gui -slevel 10 -val -slice-return main file.c
and get the following generated code:
int main(unsigned int x, unsigned int y)
{
int res;
int i;
int j;
i = 0;
while (i < 5) {
j = 0;
while (j < 5){
out_array[i][j] = (i * j) * in_array[i][i];
j ++;
}
i ++;
}
res = out_array[x][y];
return res;
}
This seems to be ok, since the x and y are not defined, so the "res" can be at any position in the out_array. I tried then with the following code:
const int in_array[5][5]={
1,2,3,4,5,
6,7,8,9,10,
11,12,13,14,15,
16,17,18,19,20,
21,22,23,24,25
};
int out_array[5][5];
int main(void)
{
int res;
int i;
int j;
for(i=0; i<5; i++){
for(j=0; j<5; j++){
out_array[i][j]=i*j*in_array[i][j];
}
}
res = out_array[3][3];
return res;
}
The result given was exactly the same. However, since I am explicitly looking for a specific position inside the array, and the loops are independent (parallelizable), I would expect the output to be something like this:
int main(void)
{
int res;
int i;
int j;
i = 3;
j = 3;
out_array[i][j]=(i * j) * in_array[i][j];
res = out_array[3][3];
}
I am not sure if is it clear from the examples. What I want to do is to identify, for a given array position, which statements impact its final result.
Thanks in advance for any support.
You obtain "the statements which impact the final result". The issue is that not all loop iterations are useful, but there is no way for the slicing to remove a statement to the code in its current form. If you perform syntactic loop unrolling, with -ulevel 5, then you will each loop iteration is individualized, and slicing can decide for each of them whether it is to be included in the slice or not. In the end, frama-c-gui -ulevel 5 -slice-return main loop.c gives you the following code
int main(void)
{
int res;
int i;
int j;
i = 0;
i ++;
i ++;
i ++;
j = 0;
j ++;
j ++;
j ++;
out_array[i][j] = (i * j) * in_array[i][j];
res = out_array[3][3];
return res;
}
which is indeed the minimal set of instructions needed to compute the value of out_array[3][3].
Of course whether -ulevel n scales up to very high values of n is another question.

Finding the center of the diameter of a graphtree using BFS?

So this function, biggest_dist, finds the diameter of a graph(the given graph in the task is always a tree).
What I want it instead to find is to find the center of the diameter, the node with the least maximum distance to all the other nodes.
I "kinda" understand the idea that we can do this by finding the path from u to t (distance between uand tis the diameter) by keeping track of the parent for each node. From there I choose the node in the middle of uand t? My question is how do I implement that for this function here? Will this make it output node 2 for this graph?
int biggest_dist(int n, int v, const vector< vector<int> >& graph)
//n are amount of nodes, v is an arbitrary vertex
{ //This function finds the diameter of thegraph
int INF = 2 * graph.size(); // Bigger than any other length
vector<int> dist(n, INF);
dist[v] = 0;
queue<int> next;
next.push(v);
int bdist = 0; //biggest distance
while (!next.empty()) {
int pos = next.front();
next.pop();
bdist = dist[pos];
for (int i = 0; i < graph[pos].size(); ++i) {
int nghbr = graph[pos][i];
if (dist[nghbr] > dist[pos] + 1) {
dist[nghbr] = dist[pos] + 1;
next.push(nghbr);
}
}
}
return bdist;
}
As a matter of fact, this function does not compute the diameter. It computes the furthest vertex from a given vertex v.
To compute the diameter of a tree, you need first to choose an arbitrary vertex (let's say v), then find the vertex that is furthest away from v (let's say w), and then find a vertex that is furthest away from w, let's sat u. The distance between w and u is the diameter of the tree, but the distance between v and w (what your function is doing) is not guaranteed to be the diameter.
To make your function compute the diameter, you will need to make it return the vertex it found alongside with the distance. Conveniently, it will always be the last element you process, so just make your function remember the last element it processed alongside with the distance to that element, and return them both. Then call your function twice, first from any arbitrary vertex, then from the vertex that the first call returned.
To make it actually find the center, you can also remember the parent for each node during your BFS. To do so, allocate an extra array, say prev, and when you do
dist[nghbr] = dist[pos] + 1;
also do
prev[nghbr] = pos;
Then at the end of the second call to the function, you can just descend bdist/2 times into the prev, something like:
center = lastVertex;
for (int i = 0; i + i < bdist; ++ i) center = prev[center];
So with a little tweaks to your function (making it return the furthest vertex from v and a vertex that is on the middle of that path, and not return the diameter at all), this code is likely to return you the center of the tree (I only tested it on your example, so it might have some off by one errors)
pair<int, int> biggest_dist(int n, int v, const vector< vector<int> >& graph)
{
int INF = 2 * graph.size(); // Bigger than any other length
vector<int> dist(n, INF);
vector<int> prev(n, INF);
dist[v] = 0;
queue<int> next;
next.push(v);
int bdist = 0; //biggest distance
int lastV = v;
while (!next.empty()) {
int pos = next.front();
next.pop();
bdist = dist[pos];
lastV = pos;
for (int i = 0; i < graph[pos].size(); ++i) {
int nghbr = graph[pos][i];
if (dist[nghbr] > dist[pos] + 1) {
dist[nghbr] = dist[pos] + 1;
prev[nghbr] = pos;
next.push(nghbr);
}
}
}
int center = lastV;
for (int i = 0; i + i < bdist; ++ i) center = prev[center];
return make_pair(lastV, center);
}
int getCenter(int n, const vector< vector<int> >& graph)
{
// first call is to get the vertex that is furthest away from vertex 0, where 0 is just an arbitrary vertes
pair<int, int> firstResult = biggest_dist(n, 0, graph);
// second call is to find the vertex that is furthest away from the vertex just found
pair<int, int> secondResult = biggest_dist(n, firstResult.first, graph);
return secondResult.second;
}

Finding Largest value in an array using recursion

This is my test array
int [] A = {1,2,7,3,5,6};
this is the method
public static int largest(int [] A)
{
int temp = A[0];
return largestRec(A, 0, A.length - 1, temp);
}
// WRITE THIS METHOD that returns the largest of the elements in A
// that are indexed from low to high. RECURSIVELY!
private static int largestRec(int [] A, int low, int high, int temp)
{
if (low == high)
return A[low];
if (low <= A.length){
if (A[low] > temp){
temp = A[low];
}
largestRec(A, low+1, high, temp);
}
return temp
}
Why does the tem reset and return A[0] which is 1?
The problem is that you are not doing anything with the return value of the recursive call to largestRec. Remember that parameters are pass by value (even in recursive calls to the same function) so changing it inside the function does not affect the outside.
I don't think you should be passing the temp as a parameter at all.
private static int largestRec(int [] A, int low, int high )
{
int temp;
if (low == high)
temp = A[low];
else
{
temp = largetstRec( A, low+1, high );
if (A[low] > temp){
temp = A[low];
}
}
return temp;
}
That keeps temp local to the function (which I think is what you probably meant be calling it temp in the first place).
private static int largestRec(int [] A, int low, int high){
var largest = A[low];
if(low == high)
return largest; // or A[high] because both are same
for(var i = low; i < high; i++){
if(largest < A[i])
largest = A[i];
}
return largest;
}

Resources