How to find the time complexity of this recursive function? - recursion

I am trying to find the time complexity of the recursive function below. I've tried to draw the tree, but it is confusing because in the if condition the function is called once, and otherwise twice.
To give some context, the function is called on nodes of a tree. The task is to calculate the max rating of each node. The rule is that if you add some node to the rating you can't add it's children to the node, but if you don't add it than you can which children to add or don't.
Here is the function:
static int solve(Node node, boolean take) {
int result;
if(take) {
result = node.rating;
for(Node child : node.children) {
result += solve(child, false);
}
return result;
}
result = 0;
for(Node child : node.children) {
result += Math.max(solve(child, true), solve(child, false));
}
return result;
}

Related

Having problem in conversion from Recursive solution to DP

Given a Binary Tree of size N, find size of the Largest Independent Set(LIS) in it. A subset of all tree nodes is an independent set if there is no edge between any two nodes of the subset. Your task is to complete the function LISS(), which finds the size of the Largest Independent Set.
I came up with this recursive solution.
int rec(struct Node *root,bool t)
{
if(root==NULL)
return 0;
if(t==true)
{
return max(1+rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
}
else
{
return max(rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
}
}
int LISS(struct Node *root)
{
int x,y;
y=rec(root,true);
return y;
}
To solve this problem via DP, I modified the code as follows, but then it gives wrong answer.
It doesn't even work with Binary tree with distinct elements.
map<int,int> mm;
int rec(struct Node *root,bool t)
{
if(root==NULL)
return 0;
if(mm.find(root->data)!=mm.end())
return mm[root->data];
if(t==true)
{
mm[root->data]=max(1+rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
return mm[root->data];
}else
{
mm[root->data]=max(rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
return mm[root-s>data];
}
}
int LISS(struct Node *root)
{
//Code here
mm={};
int y=0;
y=rec(root,true);
return max(x,y);
}
What's the mistake?
You have two states in your function but you are memoizing only one state. Let's say for root x,
rec(x,true) = 5 and
rec(x,false) = 10 .
You calculated the rec(x, true) first and saved it in your map "mm" as mm[x] = 5.
So when you are trying to get the value of rec(x, false) it is getting the value of rec(x, true) which is 5.

insertion in binary node tree using recursion

Below is my code. I'm trying to return head node back after I insert value to either left or right node. I understood the concept of insertion, but I'm unable to understand how can I return my head node back to that now it is back to original state with addition node added.
Here is exactly I don't understand.
When I insert my node how can I break the loop and return its head node back.
Recursion is stack concept which will output based on LIFO and if it is lifo how can I have head node returned back
Here's my code:
class Node {
int data;
Node left;
Node right;
}
static Node Insert(Node root,int value)
{
return nodeHelper(root,value);
}
static Node nodeHelper(Node root,int value){
Node nodeTracker = root;
Node temp;
if(root!=null){
if(value>root.data){
if(root.right==null){
temp =new Node();
temp.data = value;
root.right = temp;
return nodeTracker;
}
else{
nodeHelper(root.right,value);
}
}
else{
if(root.left==null){
temp=new Node();
temp.data = value;
root.left = temp;
return nodeTracker;
}
else{
nodeHelper(root.left,value);
}
}
}
else{
temp=new Node();
temp.data = value;
return temp;
}
}
}
To return the root of the tree, you need a third parameter that you pass around to keep track of the root. Like this:
Node* nodeHelper(Node* nodeTracker, Node* parent, int value)
Remove the local nodeTracker variable.
Your recursive calls become:
return nodeHelper(nodeTracker, parent.left, value);
(and, of course, same thing for the right branch)
And your initial call in the insert function is:
return nodeHelper(root, root, value);

Sum up the tree nodes using Java 8 Streams

Is it possible to sum up the nodes of a tree using Java 8 streams, if possible in a one liner ?
Here is a node class
public class Node
{
private int nodeNum;
ArrayList<Node> children = new ArrayList<>();
public Node(int num)
{
this.nodeNum = num;
}
public int getNodeNum()
{
return nodeNum;
}
public boolean addNode(Node node)
{
return children.add(node);
}
public ArrayList<Node> getNodes()
{
return this.children;
}
}
Normal way to solve this is using a recursion and sum up the node , like the code below.
int getNodeSum(Node node)
{
int total = 0;
if(node.children.isEmpty())
return node.getNodeNum();
else
{
for(Node tempNode:node.children)
{
total+= getNodeSum(tempNode);
}
return total+node.getNodeNum();
}
}
We can use streams to sum up the immediate child nodes but I'm not getting how to move deep and do it recursively using Streams.
This code only solves the problem to a single level. Any ideas?
total = list.stream().filter(Node -> node.children.isEmpty()).map(Node:: getNodeNum).reduce(node.getNodeNum(), (a,b) -> a+b);
One solution to your problem would be to use recursion along with Stream.flatMap.
First, you'd need to add the following helper method to your Node class:
public Stream<Node> allChildren() {
return Stream.concat(
Stream.of(this),
this.children.stream().flatMap(Node::allChildren)); // recursion here
}
This returns a Stream<Node> whose elements are this node and all its descendant nodes.
Then, you could rewrite your getNodeSum method as follows:
int getNodeSum(Node node) {
return node.allChildren()
.mapToInt(Node::getNodeNum)
.sum();
}
This uses the above defined Node.allChildren method along with the Stream.mapToInt and IntStream.sum methods to calculate the total sum.
Alternatively, you could have a Function<Node, Stream<Node>> descendants attribute in your Node class that performs the recursion in place:
private Function<Node, Stream<Node>> descendants =
node -> Stream.concat(
Stream.of(node),
node.children.stream()
.flatMap(this.descendants)); // recursion here: function invoked again
This is a recursive lambda expression, since the function you are defining is at both sides of the = sign. This kind of lambda expressions are allowed only as attributes of a class, i.e. you cannot assign a recursive lambda expression to a local variable.
With that recursive function in place, you could rewrite the allChildren method as follows:
public Stream<Node> allChildren() {
return descendants.apply(this);
}
Finally, the code for your getNodeSum method would be identical to the previous version:
int getNodeSum(Node node) {
return node.allChildren()
.mapToInt(Node::getNodeNum)
.sum();
}
Note: while this approach might result attractive for some people, it might have some drawbacks, i.e. now every instance of the Node class has the descendants attribute, despite not being needed at all. You could circumvect this i.e. by having a Tree class with this recursive function as an attribute, and Node being an inner class (with the descendants attribute removed).
You need to add recusive method for Node class, which wil be join child streams
public Stream<Node> recursiveConcat() {
return Stream.concat(
Stream.of(this),
children.stream().flatMap(Node::recursiveConcat));
}
Then do -
root.recusiveConcat().mapToInt(Node::getNodeNum).sum()
whole code
public class Node {
private int nodeNum;
ArrayList<Node> children = new ArrayList<>();
public Node(int num) {
this.nodeNum = num;
}
public int getNodeNum() {
return nodeNum;
}
public boolean addNode(Node node) {
return children.add(node);
}
public ArrayList<Node> getNodes() {
return this.children;
}
public Stream<Node> recursiveConcat() {
return Stream.concat(
Stream.of(this),
children.stream().flatMap(Node::recursiveConcat));
}
}
Node root = new Node(1);
Node node1 = new Node(2);
Node node2 = new Node(3);
Node node3 = new Node(4);
node2.addNode(node3);
node1.addNode(node2);
root.addNode(node1);
System.out.println(root.recursiveConcat().mapToInt(Node::getNodeNum).sum());

Recursive method to get the number of occurences of an element in a binary tree

Hi. I am having trouble writing this method (in the photo) in a recursuve format. The method gets the amount of occurences of a given element in the binary search tree.
To solve this recursively, I was trying to implement it with a private helper method of the same name, like this:
public int count(){
count = 0;
if (root == null)
return count;
return count (root.getInfo());
private int count(T element){
(Basically the same code you see in the photo)
}
but I ended up with overflow errors. Would you mind taking a look and telling me how I can structure this method recursively?
Cheers, and thanks.
A tentative implementation may looks like this.
public int count(T element, T root){
if(element == null) {
return 0;
}
int count = 0;
int compare = element.compareTo(root.getInfo());
if(compare == 0){
count++;
}
count += count(element, root.getLeft());
count += count(element, root.getRight());
return count;
}
count(item, root);

Binary Tree and Return root node

..I'm building a binary tree where the root is given and the children are either root-3, root-2 or root-1 (that is, they hold those number of pennies). So 5 would have nodes of 2,3,4, and so on, until the leaves are 0. Here's my method for making such a tree. I don't understand why the method doesn't return the original node, in this case, the value should be 3.
Any guidance would be awesome.
public GameNode buildTree1(GameNode root){
int penn = root.getPennies();
if (penn < 0)
{
return null;
}
else {
root.print();
root.setLeft(buildTree1(new GameNode(penn-1)));
root.setMiddle(buildTree1(new GameNode(penn-2)));
root.setRight(buildTree1(new GameNode(penn-3)));
return root;
}
Get/Set Methods
public void setLeft(GameNode newNode) {
// TODO Auto-generated method stub
left = newNode;
}
Same for setMiddle and setRight;

Resources