98. Validate Binary Search Tree
题目链接:https://leetcode.com/problems/validate-binary-search-tree/#/description
题目大意:给定一棵二叉树,判断该二叉树是否为一棵二叉查找树。二叉树的定义:1、一个节点的左子树的所有节点的值都小于该节点的值;2、一个节点的右子树的所有节点的值都大于该节点的值;3、该节点的左右子树都是二叉搜索树。
思路:对二叉树进行中序遍历,将所有元素复制到数组中,根据二叉搜索树和中序遍历的定义知道,如果该数组有序,则二叉树是二叉搜索树,否则二叉树不是一颗搜索树。
算法步骤:(1)对二叉树进行中序遍历将元素复制到数组中;(2)判断数组是否有序。
复杂度分析:遍历和比较节点的值都需要O(n)时间,所以时间复杂度为O(n),中序遍历需要使用递归,空间复杂度为O(log(n)),需要保存所有的节点值,空间复杂度为O(n),所以空间复杂度为O(n)。
代码:
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 public: 12 bool isValidBST(TreeNode* root) { 13 vector<int> nums; 14 inOrderTraversal(root, nums); 15 for (int i = 1; i < nums.size(); ++i) 16 if (nums[i] <= nums[i-1]) 17 return false; 18 return true; 19 } 20 private: 21 void inOrderTraversal(TreeNode* root, vector<int> &nums) { 22 if (!root) 23 return; 24 inOrderTraversal(root->left, nums); 25 nums.push_back(root->val); 26 inOrderTraversal(root->right, nums); 27 } 28 };
上述解法需要保存所有的节点值,其实可以进行优化,因为每次比较都只需要用到当前节点的值和前一个节点的值,所以只需要保存对当前值而言最后一次访问的节点的值。这样中序遍历需要使用递归,空间复杂度为O(log(n)),所以优化后的算法空间复杂度为O(log(n))。
代码:
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 public: 12 bool isValidBST(TreeNode* root) { 13 TreeNode* pre = nullptr; 14 return isValidBST(root, pre); 15 } 16 private: 17 bool isValidBST(TreeNode* root, TreeNode* &pre) { 18 if (!root) 19 return true; 20 if (!isValidBST(root->left, pre)) 21 return false; 22 if (pre && root->val <= pre->val) 23 return false; 24 pre = root; 25 return isValidBST(root->right, pre); 26 } 27 };
评测系统上运行结果: