Write a program which takes two nodes in a BST and a third node, the “middle”
node, and determines if one of the two nodes is a proper ancestor and the other a
proper descendant of the middle. (A proper ancestor of a node is an ancestor that
is not equal to the node; a proper descendant is defined similarly.) For example, in
Figure , if the middle is Node /, your function should return true if
the two nodes are {A,K] or j/, M|. It should return false if the two nodes are [1,P| or
{],K}. You can assume that all keys are unique. Nodes do not have pointers to their
parents

CODE:
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
//this function is to check wheather middle node is in between node1 and node2 i.e node 1/2 can be ancestor subsequently node1/2 can be descendant of middle
bool isMiddleNodeBetweenTwoNodes(TreeNode* middle,TreeNode* node1,TreeNode* node2){
//we can traverse from both nodes and check we will hit middle or not if not node1 will hit node2 without hitting middle
auto n1=node1,n2=node2;
while(n1!=node2 && n2!=node1 && n1!=middle && n2!=middle && (n1||n2)){
if(n1) n1=middle->val<n1->val?n1->left:n1->right;
if(n2) n2=middle->val<n2->val?n2->left:n2->right;
}
//neither n1 and n2 does not hit middle there will be 2 chances
//1)n1 hit the other node2 or vice versa 2)n1 or n2 will be null
if((n1!=middle &&!n2!=middle) || n1==node2 || n2==node1) return 0;
//here either n1 or n2 hits middle we want to find middle will hit other node or not
return n1==middle?reachTarger(middle,node2):reachTarger(middle,node1);
}
bool reachTarger(TreeNode* from,TreeNode* to){
TreeNode* curr=from;
while(curr && curr!=to){
curr=to->val<curr->val?curr->left:curr->right;
}
return curr==to;
}
};