Given preorder and inorder traversal of a tree, construct the binary tree.

**Hint:**

A good way to attempt this question is to work backwards. Approach this question by drawing a binary tree, then list down its preorder and inorder traversal. As most binary tree problems, you want to solve this recursively.

**About Duplicates:**

In this solution, we will assume that duplicates are not allowed in the binary tree. Why?

Consider the following case:

preorder = {7, 7} inorder = {7, 7}

We can construct the following trees which are both perfectly valid solutions.

7 7 /or\ 7 7

Clearly, there would be ambiguity in constructing the tree if duplicates were allowed.

**Solution:**

Let us look at this example tree.

_______7______ / \ __10__ ___2 / \ / 4 3 _8 \ / 1 11

The preorder and inorder traversals for the binary tree above is:

preorder = {7,10,4,3,1,2,8,11} inorder = {4,10,3,1,7,11,8,2}

The crucial observation to this problem is *the tree’s root always coincides with the first element in preorder traversal*. This must be true because in preorder traversal you always traverse the root node before its children. The root node’s value appear to be **7** from the binary tree above.

We easily find that **7** appears as the 4^{th} index in the inorder sequence. (Notice that earlier we assumed that duplicates are not allowed in the tree, so there would be no ambiguity). For inorder traversal, we visit the left subtree first, then root node, and followed by the right subtree. Therefore, all elements left of **7** must be in the left subtree and all elements to the right must be in the right subtree.

We see a clear recursive pattern from the above observation. After creating the root node (**7**), we construct its left and right subtree from inorder traversal of {4, 10, 3, 1} and {11, 8, 2} respectively. We also need its corresponding preorder traversal which could be found in a similar fashion. If you remember, preorder traversal follows the sequence of root node, left subtree and followed by right subtree. Therefore, the left and right subtree’s postorder traversal must be {10, 4, 3, 1} and {2, 8, 11} respectively. Since the left and right subtree are binary trees in their own right, we can solve recursively!

We left out some details on how we search the root value’s index in the inorder sequence. How about a simple *linear search*? If we assume that the constructed binary tree is always balanced, then we can guarantee the run time complexity to be O(*N* log *N*), where *N* is the number of nodes. However, this is not necessarily the case and the constructed binary tree can be skewed to the left/right, which has the worst complexity of O(*N*^{2}).

A more efficient way is to eliminate the search by using an efficient look-up mechanism such as *hash table*. By hashing an element’s value to its corresponding index in the inorder sequence, we can do look-ups in constant time. Now, we need only O(*N*) time to construct the tree, which theoretically is the most efficient way.

For illustration purpose, the below code uses a simple array for table look-up, which is restricted to elements of 0 to 255 only. You should be able to extend it easily to use a hash table.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
const int MAX = 256; // a fast lookup for inorder's element -> index // binary tree's element must be in the range of [0, MAX-1] int mapIndex[MAX]; void mapToIndices(int inorder[], int n) { for (int i = 0; i < n; i++) { assert(0 <= inorder[i] && inorder[i] <= MAX-1); mapIndex[inorder[i]] = i; } } // precondition: mapToIndices must be called before entry Node *buildInorderPreorder(int in[], int pre[], int n, int offset) { assert(n >= 0); if (n == 0) return NULL; int rootVal = pre[0]; int i = mapIndex[rootVal]-offset; // the divider's index Node *root = new Node(rootVal); root->left = buildInorderPreorder(in, pre+1, i, offset); root->right = buildInorderPreorder(in+i+1, pre+i+1, n-i-1, offset+i+1); return root; } |

Now, if we are given* inorder and postorder* traversal, can we construct the binary tree?

The answer is yes, using very similar approach as above. Below is the code:

1 2 3 4 5 6 7 8 9 10 11 |
// precondition: mapToIndices must be called before entry Node *buildInorderPostorder(int in[], int post[], int n, int offset) { assert(n >= 0); if (n == 0) return NULL; int rootVal = post[n-1]; int i = mapIndex[rootVal]-offset; // the divider's index Node *root = new Node(rootVal); root->left = buildInorderPostorder(in, post, i, offset); root->right = buildInorderPostorder(in+i+1, post+i, n-i-1, offset+i+1); return root; } |

**Further Thoughts:**

- If we are given
*preorder and postorder*traversal, can we construct the binary tree? Why or why not? - Given
*preorder, inorder, and postorder*traversal, how can you verify if these traversals are referring to the*exact same*binary tree? - Remember from my earlier post: Serialization/Deserialization of a Binary Tree? It is trivial to see this as an alternative method to serialize/deserialize a binary tree. 🙂

The post order could already recover the whole tree. While need inorder and post order together?

In your Serialization/Deserialization of a Binary Tree, you also just use post order to recover. .

-15Postorder alone could not construct the binary tree, unless it is a sorted binary tree (BST). My example above purposely used an unordered binary tree to avoid assumption that the binary tree is sorted. To serialize/deserialize using preorder/postorder alone you have to store extra sentinels along with the nodes’ value.

+14Can you clarify what exactly the offset and divider’s index are and their importance to the algorithm?

+3The divider’s index is just the index of the root value in the inorder sequence.

The offset is used for the mapIndex[] array only. mapIndex[] array maps a value to index in the inorder array. However, when we separate the tree into its right subtree, the corresponding inorder subarray is passed in as in+i+1. This alters the original index of the array and it won’t work if we use mapIndex[] directly. Therefore, we need to record the offset from the original array.

0What is the offset initially be called with. Can you pls provide the call method parameters.

Thanks

0the initial offset should be zero.. the offset+i+1 is done since in+i+1 is done. Since we start with in+i+1, our indexes should be -(i+1).

For implementation without offset and mapIndex check here

But obviously, its slower than map version. 🙂

+2Contribute my code :

#include

#include

using namespace std;

struct node{

node* left;

node* right;

int data;

};

node* root;

void buildtree(node *b, int left_selected ,int* preorder, int* inorder){

int preorder_1[8] = {-1,-1,-1,-1,-1,-1,-1,-1};

int preorder_2[8] = {-1,-1,-1,-1,-1,-1,-1,-1};

int inorder_1[8] = {-1,-1,-1,-1,-1,-1,-1,-1};

int inorder_2[8] = {-1,-1,-1,-1,-1,-1,-1,-1};

int i, j, k1, k2;

//insert preorder[0];

if(b==NULL){

root = b = new node;

b->data = preorder[0];

b->left = b->right = NULL;

}

else{

node* tmp = new node;

tmp->data = preorder[0];

tmp->left = tmp->right = NULL;

if(left_selected)

b->left = tmp;

else

b->right = tmp;

b = tmp;

}

i = 0;

while(inorder[i] != preorder[0]){

inorder_1[i] = inorder[i];

i++;

}

i++;

j = 0;

while(inorder[i] != -1 ){

inorder_2[j] = inorder[i];

j++;

i++;

}

i = j = k1 = k2 = 0;

while(preorder[i] != -1 ){

i++;

int flag = false;

j = 0;

while(inorder_1[j] != -1 ){

if (inorder_1[j] == preorder[i]){

flag = true;

break;

}

j++;

}

if(flag){

preorder_1[k1] = preorder[i];

k1++;

}

else{

preorder_2[k2] = preorder[i];

k2++;

}

}

if(preorder_1[0] != -1)

buildtree(b, 1, preorder_1, inorder_1);

if(preorder_2[0] != -1)

buildtree(b, 0, preorder_2, inorder_2);

}

int main()

{

root = NULL;

int preorder[] = {7,10,4,3,1,2,8,11,-1};

int inorder[] = {4,10,3,1,7,11,8,2,-1};

buildtree(root, 1 ,preorder, inorder);

return 1;

}

0Following is my codes. The same algorithm as introduced here.

template

void binaryTree::constructTreeFromPreorderInorderSets()

{

vector preorderSet;

vector inorderSet;

cout <> numberNodes;

cout << "Input preorder set one by one:" << endl;

T tmp;

for( int i = 0 ; i > tmp;

preorderSet.push_back( tmp );

}

cout << "Input inorder set one by one:" << endl;

for( int i = 0 ; i > tmp;

inorderSet.push_back( tmp );

}

int p = 0;

bool * nodeAdded = new bool[ numberNodes ];

for( int i = 0 ; i < numberNodes; i ++ ) nodeAdded[i] = false;

constructTreeRecurselyInorderPreorder( 0, numberNodes-1, p, root, preorderSet, inorderSet, nodeAdded, numberNodes );

}

template

void binaryTree::constructTreeRecurselyInorderPreorder( int begin, int end, int & p, treeNode * & subroot, const vector & preorderSet, const vector & inorderSet, bool * nodeAdded, const int & numberNodes )

{

if( begin > end ) return;

subroot = new treeNode( preorderSet[p], NULL, NULL );

int i,j; //position of A[p] at set B (suppose A is preorder set, B is inorder set)

//we must compare in each small segment: begin-end

for( i = begin ; i = numberNodes )

{

cerr << "Error:" << "preorderSet["<<p<<"]=" << preorderSet[p]<leftChild, preorderSet, inorderSet, nodeAdded, numberNodes );

constructTreeRecurselyInorderPreorder( j+1, end, p, subroot->rightChild, preorderSet, inorderSet, nodeAdded, numberNodes );

}

-2thanks mate 🙂

0For problem 1 “If we are given preorder and postorder traversal, can we construct the binary tree? Why or why not?”, I think the answer is no, right? I think there will be problem with leaves whose parent has only 1 child because in such case such leaf can be either left or right child.

+7Hi,

I have different answer however. Following is my explanation. How do you think?

1. Given preorder and postorder traversal, we can still construct the binary tree. For the preorder, the first is root node, followed by nodes of the left subtree, followed by nodes of the right subtree. For the postorder, the last is root node, in front of which they are the nodes of the right subtree, in front of which they are the nodes of the left subtree. So, the second last element in the postorder will be the root node of the right subtree. Finding the position of the root node of the right subtree in the preorder, then the preorder can be partitioned into three parts: root node, followed by the nodes of the left subtree, followed by the nodes of the right subtree. The later two parts can be constructed into left subtree and right subtree respectively and recursively. For the post order, it can also be partitioned into three parts by coounting the number of nodes in each part. In fact, in recursion function, we always reconstruct the right subtree first and then left subtree, and decrease the index for postorder by one in each recursion. Then the index for the postorder will always point to the right element.

//Then, Therefore, we can see that we can still construct the binary tree given the preorder and postorder

//traversal.

+1but i am having some different answer.we can only construct full binary tree(all nodes except last leaf level two child nodes)and the strictly binary tree(if n leaf node then 2n-1 total nubers of nodes) if the preorder and post order is given.because for all the other trees post and pre order may be same but not the inorder is same.So the resultant tree may yield different structures for all binary tree except full binary and strictly binary tree.

+1please sir give me one example to make a tree…..by both pre or post

0Henian, forget my previous post. You are right. I agree with you now.

+1i want to represent in an array and it should perform the operations of inorder ,preorder,postorder with out using linked list and with out traversal it should be in an level wise.how can i ?

+1How to answer the second question please: Given preorder, inorder, and postorder traversal, how can you verify if these traversals are referring to the exact same binary tree?

Thanks!

+1A preorder, inorder or postorder traversal can come from more than two different binary trees. For example, given an inorder traversal {4, 2, 5, 1, 6, 3, 7}, any element can be viewed as the root node of the binary tree, generating different binary trees. So I don’t think we can verify if these traversals are referring to the exact same binary tree.

+1A little pythonic.

def maketree(preorder, inorder):

global tree

if len(preorder) == 0:

return None

root = preorder[0]

ind = inorder.index(root)

linorder = filter(lambda x: inorder.index(x) ind, inorder)

lpreorder = filter(lambda x: x in linorder, preorder)

rpreorder = filter(lambda x: x in rinorder, preorder)

tree[root] = [maketree(lpreorder, linorder), maketree(rpreorder, rinorder)]

return root

`tree = {}`

pO = [7,10,4,3,1,2,8,11]

iO = [4,10,3,1,7,11,8,2]

maketree(pO, iO)

print tree

</code

+5Can you give a logic answer for the second question?

If we are given preorder and postorder traversal, can we construct the binary tree? Why or why not?+1Sorry, I mean *first question!

-1http://anandtechblog.blogspot.com/2011/06/construct-given-tree-from-pre-order-and.html

0Pingback: Construct Binary Tree From Inorder and Preorder/Postorder Traversal | 口├人人│의 Blog

I have C# variant of this code available at

http://tryingout101.blogspot.com/2011/08/deserializing-binary-tree-from-inorder.html

-1Hi 1337,

For the second problem in further thought, I don’t think we can verify if these traversals are referring to the exact same binary tree.

A preorder, inorder or postorder traversal can come from more than two different binary trees.

For example, given an inorder traversal {4, 2, 5, 1, 6, 3, 7}, any element can be viewed as the root node of the binary tree, generating different binary trees.

How do you think?

-2With preorder and inorder, we first construct a tree. Then we use postorder to print this tree, and compare the printout with our given postorder array. This way, we can verify the answer.

+2The code is a little hard to understand. I have tried to copy it and run the given code myself to get a better understanding. I am not sure how many of you have done this, but after my analyse, the code to build tree from inorder and preorder will give us the tree differently, which the last node 11 is the right node of 8. Can anyone verify this?

const int TREE_SIZE = 8;

int in_order[TREE_SIZE] = {4, 10, 3, 1, 7, 8, 11, 2};

int pre_order[TREE_SIZE] = {7, 10, 4, 3, 1, 2, 8, 11};

const int MAX = 256;

int mapIndex[MAX];

for (int i = 0; i < TREE_SIZE; i++)

{

mapIndex[in_order[i]] = i;

}

buildInorderPreorder( in_order, pre_order, TREE_SIZE, 0, mapIndex);

0Sorry, my bad, I apparently have used the wrong array of inorder.

0Minor bug: The method cannot deal with duplicate bcs the mapping will only record the last occurrence of number, the latter 2 in your example tree.

-3In my post, I already mentioned: “In this solution, we will assume that duplicates are not allowed in the binary tree.”

+1Here is a Java Version of the same problem

http://www.technicalypto.com/2011/12/reconstruct-binary-tree-given-its.html

0Actually you can simplify it by remove argument in[ ]. Since you never actually use it in function.

0it is too much complex!!!!

0here is a slightly simpler to understand version of your solution:

Node *buildInorderPreorder(int mapIndex[], int pre[], int lo, int hi) {

if (hi left = buildInorderPreorder(mapIndex, pre+1, lo, i);

root->right = buildInorderPreorder(mapIndex, pre+i-lo+1, i+1, hi);

return root;

}

You dont really need the array in, because the only role of in is to determine the dividers index i, but i is more efficiently determined with the hash table mapIndex.

Instead of n and offset, I think the algorithm is simpler to understand in terms of indices lo and hi. In each recursion step, the range (lo, hi) is divided into (lo,i) and (i+1,hi). The recursion ends when the range is empty.

00Has this question been

reallyasked in an interview. It seems way too complicated. Am I the only one here thinking it is too much?0I mean even your code is not perfect.You use

as a parameter in the methods and do pointer arithmetic passing it as argument in subsequent calls but this parameter is actually redudant and not used in the code.This makes the code not readable which IMO it is something important in an interview.

+1I think 1337 should delete the parameter “int[] in” in the recursion. in[] has no use after you got mapIndex array

+1Hi 1337c0d3r, I found in your buildInorderPreorder, the use of the divider’s index and offset is a little complicated. Can I instead use the common (start, end) pair to specify the range? The only thing that need to be taken care of is when to increment the root’s index in the pre_order[]. The following is my code with the same algorithm. Please let me know if you find anything wrong.

0Hi 1337c0d3r, if duplicates are allowed, is it possible to build a binary tree from Inorder and Preorder/Postorder Traversal ?

0is it possible to reconstruct a unique tree from give anyone of three traversal order?

0So according to you

1) Search for ROOT

2) Then on Left and Right sub tree apply Binery Search Tree

Then the resulting tree would be :-

7

/ \

10 11

/ \

4 8

/ /

3 2

/

1

Right ?

0Ok ^^^ See my tree here 😛

-2May I simply say what a relief to uncover someone that truly understands what they’re talking about online. You certainly realize how to bring an issue to light and make it important. More and more people really need to read this and understand this side of your story. I was surprised that you’re not more popular given that you certainly have the gift.

-2In Java:

(Recursive methods can be converted to in-place for further optimization)

+4Here’s in place version of the same java implementation of mine:

+1I found a tutorial here http://bloggerplugnplay.blogspot.in/2012/11/construction-of-binary-tree-from.html

0For the linear search, when the tree is perfectly balanced, the time should be n/2 rather than logn, right?

0The total time complexity is O(logN log N)

0Pingback: Amazon interview preparation | What I learn, I blog !

Pingback: leetcode: Construct Binary Tree from Inorder and Postorder/Preorder Traversal solution | 烟客旅人 sigmainfy

Good day! I simply would like to give a massive thumbs up for the truly amazing information you

have here for this subject post. I shall be coming back on the weblog for more

soon.

0This code contains a run-time error, modified code is as follows..

int mapIndex[20];

void mapToIndices()

{

for (int i = 0; i < cnt; i++)

{

mapIndex[inorder[i]] = i;

}

}

// precondition: mapToIndices must be called before entry

Node buildInorderPreorder(int in[], int pre[], int n)

{

if (n 1)

{

root->left = buildInorderPreorder(in, pre+1, i);

root->right = buildInorderPreorder(in+i+1, pre+i+1, n-i-1);

}

return root;

}

Node buildInorderPostorder(int in[], int post[], int n)

{

if (n 1)

{

root->left = buildInorderPostorder(in, post, i);

root->right = buildInorderPostorder(in+i+1, post+i, n-i-1);

}

return root;

}

0i did this in no time and is a much easier way of solving this problem

#include

using namespace std;

struct node

{

int data;

node *left,*right;

}*root;

int inorder[]={4,10,3,1,7,11,8,2};

int preorder[]={7,10,4,3,1,2,8,11};

int j=0;

node* check(int a,int b)

{

node *temp;

temp=new node;

if(a>b)

return NULL;

for(int i=a;idata=preorder[j++];

temp->left=check(a,i-1);

temp->right=check(i+1,b);

}

return temp;

}

void display(node *sr)

{

if(sr!=NULL)

{

cout<data<left);

display(sr->right);

}

return;

}

int main()

{

root=NULL;

root=check(0,7);

cout<<"The preorder traversal: ";

display(root);

system("pause");

return 0;

}

0simpler approach using binary search for root-val

0simpler approach using binary search for root-val

+1Your explanation is very helpful.

+1answer to: if three orders are given, find whether they beling to the same tree of not

First confirm if all the orders have the same number of elements.

Using inorder and postrder, we can find preorder and after finding each element, we can compare it with the given preorder. If it does not match at any instant, it means the orders are not of a single BT

+1public class Solution {

int pre;

public TreeNode buildTree(int[] preorder, int[] inorder) {

// Start typing your Java solution below

// DO NOT write main() function

pre = 0;

if(preorder.length == 0){return null;}

return build(preorder, inorder, 0, preorder.length-1);

}

public TreeNode build(int[] preorder, int[] inorder, int left, int right){

if(left > right){

return null;

}

//if(pre > preorder.length){

// return null;

//}

int key = preorder[pre];

pre++;

TreeNode tn = new TreeNode(key);

int i = 0;

for(i = left; i <= right; i++){

if(inorder[i] == key){break;}

}

tn.left = build(preorder, inorder, left, i-1);

tn.right = build(preorder, inorder, i+1, right);

return tn;

}

}

+1this is helpfull for practice…..

+10is it safe to remove these codes?

0I agree with @SHawn, and some people else that in[] is not needed in the function

. in[] is only used in the function

.

0its wrong in the explanation == “Therefore, the left and right subtree’s postorder traversal must be {10, 4, 3, 1} and {2, 8, 11} respectively. ”

but it should be== “Therefore, the left and right subtree’s preorder traversal must be {10, 4, 3, 1} and {2, 8, 11} respectively. ”

just look at the tree..

+2I need a simple programming code for Construct Binary Tree From Inorder and Preorder/Postorder Traversal

0So we’re sending a letter to the other side’s attorney as to this truth and plan to

complain to the state bar.

-1very nice

0You need to be a part of a contest for one of the most useful sites online.

I’m going to recommend this blog!

0Howdy I am so excited I found your blog page, I really found

you by accident, while I was searching on Google for something else, Nonetheless I am here

now and would just like to say thank you for a remarkable post and a all round exciting blog (I also love the theme/design), I don’t have time to read through it all at the minute but I have

book-marked it and also included your RSS feeds, so when I have time I will

be back to read a great deal more, Please do keep up the excellent work.

0Hi there Dear, are you actually visiting this web site on a

regular basis, if so afterward you will definitely get pleasant knowledge.

-1It’s really a nice and useful piece of info. I am satisfied that you just shared this helpful information with

us. Please stay us up to date like this. Thanks for sharing.

0Quality articles is the key to invite the users to pay

a quick visit the site, that’s what this website is providing.

-1My spouse and I stumbled over here by a different page and thought I should

check things out. I like what I see so now i am following you.

Look forward to finding out about your web page again.

0Pingback: LeetCode 105: Construct Binary Tree from Preorder and Inorder Traversal (Medium) | helloyuan

That is really interesting, You are a very professional blogger.

I’ve joined your rss feed and stay up for

in search of more of your fantastic post. Additionally, I’ve shared your site in my

social networks

0veri good

0Pingback: Construct Binary Tree from Preorder and Inorder Traversal | ggGrace's Blog

how to construct a binary tree from pre order and post order?…………

pleaze give brief about this

and an example too………..!

0Hi this is somewhat of off topic but I was wanting to know

if blogs use WYSIWYG editors or if you have to manually code with HTML.

I’m starting a blog soon but have no coding know-how so I wanted

to get advice from someone with experience. Any help

would be enormously appreciated!

0Hello! This post could not be written any better! Reading this post reminds me of my previous room mate!

He always kept chatting about this. I will forward this page to him.

Fairly certain he will have a good read. Thank you for sharing!

0I would like to thank you for the efforts you’ve put

in writing this website. I really hope to view the same high-grade content from you later on as well.

In fact, your creative writing abilities has encouraged me to get my own, personal site now

😉

0Wonderful beat ! I would like to apprentice while you amend your website, how could i subscribe for a

blog site? The account helped me a acceptable deal. I had been tiny bit acquainted of this your broadcast offered bright clear concept

0Actually when someone doesn’t understand then its up to other users that they will assist, so here it

occurs.

0Great web site. Lots of helpful information here.

I am sending it to a few buddies ans also sharing in delicious.

And certainly, thank you for your effort!

0Simply desire to say your article is as astonishing.

The clarity for your put up is just nice and i can assume you are a professional on this subject.

Well together with your permission allow me to grasp your feed to

stay up to date with forthcoming post. Thanks one million and please keep up the

enjoyable work.

0Excellent article. Keep writing such kind of info on your site.

Im really impressed by it.

Hey there, You’ve performed a fantastic job. I’ll certainly digg it and in my view recommend

to my friends. I am confident they’ll be benefited from this website.

0I do consider all the ideas you have offered for your post.

They’re very convincing and will definitely work. Still, the posts are too brief for

newbies. May just you please lengthen them a little from subsequent

time? Thanks for the post.

0Hey very nice web site!! Man .. Excellent .. Amazing .. I’ll bookmark your web site and take

the feeds additionally? I’m happy to find so many helpful information here within the put up, we’d like

work out extra strategies on this regard, thanks for sharing.

. . . . .

0I think what you posted was very logical. However, what about this?

suppose you added a little information? I ain’t saying your information isn’t solid, however what

if you added something that grabbed people’s attention? I mean Construct Binary Tree From Inorder

and Preorder/Postorder Traversal – LeetCode is kinda

boring. You ought to look at Yahoo’s home page and note how they create article titles to get people

to open the links. You might add a video or a related pic or two to get people interested about what you’ve got to say.

In my opinion, it could bring your posts a little livelier.

-1Fantastic web site. Plenty of helpful information here.

I’m sending it to a few buddies ans also sharing in delicious.

And naturally, thank you to your sweat!

0Greetings I am so grateful I found your site, I really found you

by accident, while I was looking on Yahoo for something else, Anyways I am here now and would just like to say cheers

for a tremendous post and a all round thrilling

blog (I also love the theme/design), I don’t have time to go through it all

at the moment but I have bookmarked it and also added in your RSS feeds,

so when I have time I will be back to read a

great deal more, Please do keep up the great work.

0Good way of describing, and good post to

get facts regarding my presentation subject matter, which i am going to present in university.

0I like the helpful information you provide on your articles.

I will bookmark your weblog and test once more here frequently.

I am somewhat sure I will be informed many new stuff

right here! Best of luck for the next!

0I have noticed you don’t monetize your website, don’t waste your traffic,

you can earn extra cash every month. You can use the best adsense

alternative for any type of website (they approve all websites), for more details simply search in gooogle:

boorfe’s tips monetize your website

0