The first solution works for a general binary tree where we can't rely on any ordering of the nodes:

```
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root) { return nullptr; }
if (root == p || root == q) { return root; }
auto l = lowestCommonAncestor(root->left, p, q), r = lowestCommonAncestor(root->right, p, q);
return l && r ? root : l ? l : r;
}
};
```

The second solution assumes a BST ordering to avoid searching much of the tree:

```
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (p->val > q->val) { std::swap(p, q); }
while (root->val < p->val || root->val > q->val) {
while (root->val < p->val) { root = root->right; }
while (root->val > q->val) { root = root->left; }
}
return root;
}
};
```