Algorithms-UCSanDiego

Data Structures and Algorithms by UCSanDiego

View project on GitHub

3. Is Binary Search Tree (duplicate values)

Problem

Solutions

CPP

    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <memory>
    #include <iterator>
    #include <algorithm>
    #include <limits>
    #include <unordered_set>

    using namespace std;

    using Type = long long;
    constexpr Type INF = numeric_limits< Type >::max();

    struct TreeNode;
    using HTreeNode = shared_ptr< TreeNode >;
    struct TreeNode {
        Type val, min, max;
        HTreeNode left, right;
        TreeNode( Type val, Type min=-INF, Type max=INF )
            : val{ val }, min{ min }, max{ max }, left{ nullptr }, right{ nullptr } {}
        friend ostream& operator<<( ostream& os, const HTreeNode& node ){
            if( node )
                os << node->val;
            return os;
        }
    };
    bool operator<( const HTreeNode& lhs, const HTreeNode& rhs ){
        return lhs->val < rhs->val;
    }
    using Collection = vector< HTreeNode >;

    namespace failed_case_40_of_95_unknown_signal_11 { // stack overflow
        class Solution {
        public:
            bool isBST( HTreeNode root ){
                auto ok{ true };
                if( root )
                    go( root, ok );
                return ok;
            }
        private:
            using MinMax = pair< Type,Type >;
            MinMax go( HTreeNode root, bool& ok ){
                if( ! ok )
                    return{ 0,0 };
                if( ! root->left && ! root->right )
                    return{ root->val, root->val };
                auto[ L1, L2 ] = root->left?  go( root->left,  ok ) : make_pair( root->val, root->val );
                auto[ R1, R2 ] = root->right? go( root->right, ok ) : make_pair( root->val, root->val );
                if( root->left && max( L1, L2 ) >= root->val )
                    ok = false;
                if( root->right && root->val > min( R1, R2 ) )
                    ok = false;
                return{  max({ root->val, L1, L2, R1, R2 }),
                         min({ root->val, L1, L2, R1, R2 })  };
            }
        };
    } // namespace failed_case_40_of_95_unknown_signal_11

    namespace failed_case_44_of_95_unknown_signal_11 { // stack overflow
        class Solution {
        public:
            bool isBST( HTreeNode root, Type min=numeric_limits< Type >::min(), Type max=numeric_limits< Type >::max() ){
                return go( root, min, max );
            }
        private:
            bool go( HTreeNode root, Type min, Type max ){
                if( ! root )
                    return true;
                if( min > root->val || root->val >= max )
                    return false;
                return go( root->left, min, root->val ) &&
                       go( root->right, root->val, max );
            }
        };
    } // namespace failed_case_44_of_95_unknown_signal_11

    class Solution {
    public:
        bool isBST( HTreeNode node, Collection stack={} ){ // iterative post-order traversal
            if( node )
                stack.push_back( node );
            while( ! stack.empty() ){
                node = stack.back(), stack.pop_back();
                if( node->min > node->val || node->val >= node->max )
                    return false;
                if( node->right ){ // push right child to stack first, so left child is processed first
                    node->right->min = node->val;
                    node->right->max = node->max;
                    stack.push_back( node->right );
                }
                if( node->left ){
                    node->left->min = node->min;
                    node->left->max = node->val;
                    stack.push_back( node->left );
                }
            }
            return true;
        }
    };

    int main() {
        string line;
        auto N{ 0 }; {
            getline( cin, line );
            istringstream is{ line };
            is >> N;
        }
        Collection A;
        generate_n( back_inserter( A ), N, [](){ return make_shared< TreeNode >( 0 ); });
        for( auto i{ 0 }; i < N && getline( cin, line ); ++i ){
            istringstream parser{ line };
            auto val{ 0 }, L{ 0 }, R{ 0 };
            parser >> val >> L >> R;
            A[ i ]->val = val;
            A[ i ]->left =  ( -1 < L )? A[ L ] : nullptr;
            A[ i ]->right = ( -1 < R )? A[ R ] : nullptr;
        }
        auto ok = A.empty() || Solution().isBST( A[ 0 ] );
        cout << ( ok? "CORRECT" : "INCORRECT" ) << endl;
        return 0;
    }