Inorder traversal ( left → root → right ) is strictly increasing, that much is obvious. But, a tree is a BST iff inorder traversal is strictly increasing.
Why? [left subtree] < x < [right subtree] If the invariant holds recursively, you can say all nodes in left subtree < x < all nodes in right subtree
Is Valid BST ( another solution )
bool isValidBST(TreeNode* root) {
long long prev = LLONG_MIN;
auto f = [&](auto&& f, TreeNode* root) -> bool {
if (!root) return true;
if (!f(f, root->left)) return false;
if (prev >= root->val) return false;
prev = root->val;
return f(f, root->right);
};
return f(f, root);
}Kth smalles value in BST
Notice the early termination and the compact style
int kthSmallest(TreeNode* root, int k) {
int ans;
auto f = [&](auto&& f, TreeNode* root) -> bool {
if (!root) return false;
if (f(f, root->left)) return true;
if (--k == 0) return ans = root->val, true;
return f(f, root->right);
};
f(f, root);
return ans;
}Recover BST
The trick part is handling both two and one inversion case cleanly.
2 inversion case
valid: 1 2 3 4 5 6
swapped: 1 5 3 4 2 6
↑ ↑
inversion 1
5 > 3
inversion 2
4 > 2
what got swapped? if cur is the RHS val
prev of cur ( inv1 ) and cur ( inv2 )
1 inversion case
valid: 1 2 3
swapped: 1 3 2
inversion
3 > 2
prev of cur AND the cur
so you can only set the first one on the first inv and keep on
updating the second one
void recoverTree(TreeNode* root) {
// inversions in inorder traversal
// note: you cannot do TreeNode* prev, first, second
// * associates with the var not type
TreeNode *prev, *first, *second;
prev = first = second = nullptr;
auto f = [&](auto&& f, TreeNode* root) {
if(!root) return;
f(f,root->left);
if(prev && prev -> val > root->val){
if(!first) first = prev;
second = root;
}
prev = root;
f(f,root->right);
};
f(f,root);
swap(first -> val, second -> val);
}