本节内容
654.最大二叉树
617.合并二叉树
700.二叉搜索树中的搜索
98.验证二叉搜索树
654.最大二叉树※ 建议 :又是构造二叉树,昨天大家刚刚做完 中序后序确定二叉树,今天做这个 应该会容易一些, 先看视频,好好体会一下 为什么构造二叉树都是 前序遍历
题目链接: https://leetcode.cn/problems/maximum-binary-tree/ 文章讲解: https://programmercarl.com/0654.%E6%9C%80%E5%A4%A7%E4%BA%8C%E5%8F%89%E6%A0%91.html 视频讲解: https://www.bilibili.com/video/BV1MG411G7ox/?vd_source=d0597ba9769fffd49ab31d067e3fe824
题目分析
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 输入:nums = [3,2,1,6,0,5] 输出:[6,3,5,null,2,0,null,null,1] 解释:递归调用如下所示: - [3,2,1,6,0,5] 中的最大值是 6 ,左边部分是 [3,2,1] ,右边部分是 [0,5] 。 - [3,2,1] 中的最大值是 3 ,左边部分是 [] ,右边部分是 [2,1] 。 - 空数组,无子节点。 - [2,1] 中的最大值是 2 ,左边部分是 [] ,右边部分是 [1] 。 - 空数组,无子节点。 - 只有一个元素,所以子节点是一个值为 1 的节点。 - [0,5] 中的最大值是 5 ,左边部分是 [0] ,右边部分是 [] 。 - 只有一个元素,所以子节点是一个值为 0 的节点。 - 空数组,无子节点。
示例 2:
1 2 输入:nums = [3,2,1] 输出:[3,null,2,null,1]
方案一 递归遍历,每次都去找最大的。来生成二叉树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Solution { public TreeNode constructMaximumBinaryTree (int [] nums) { return recursion(nums, 0 , nums.length - 1 ); } private TreeNode recursion (int [] nums, int start, int end) { if (start > end) return null ; int index = findIndex(nums, start, end); TreeNode node = new TreeNode (nums[index]); node.left = recursion(nums, start, index - 1 ); node.right = recursion(nums, index + 1 , end); return node; } private int findIndex (int [] nums, int start, int end) { if (start == end) return start; int max = nums[start]; int index = start; for (int i = start; i <= end; i++) { if (nums[i] > max) { max = nums[i]; index = i; } } return index; } }
结果 解答成功: 执行耗时:2 ms,击败了87.09% 的Java用户 内存消耗:42.4 MB,击败了59.40% 的Java用户
代码随想录 https://programmercarl.com/0654.%E6%9C%80%E5%A4%A7%E4%BA%8C%E5%8F%89%E6%A0%91.html
思路 最大二叉树的构建过程如下:
构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。
参数传入的是存放元素的数组,返回该数组构造的二叉树的头结点,返回类型是指向节点的指针。
代码如下:
1 TreeNode* constructMaximumBinaryTree (vector<int >& nums)
题目中说了输入的数组大小一定是大于等于1的,所以我们不用考虑小于1的情况,那么当递归遍历的时候,如果传入的数组大小为1,说明遍历到了叶子节点了。
那么应该定义一个新的节点,并把这个数组的数值赋给新的节点,然后返回这个节点。 这表示一个数组大小是1的时候,构造了一个新的节点,并返回。
代码如下:
1 2 3 4 5 TreeNode* node = new TreeNode (0 );if (nums.size () == 1 ) { node->val = nums[0 ]; return node; }
这里有三步工作
先要找到数组中最大的值和对应的下标, 最大的值构造根节点,下标用来下一步分割数组。
代码如下:
1 2 3 4 5 6 7 8 9 10 int maxValue = 0 ;int maxValueIndex = 0 ;for (int i = 0 ; i < nums.size (); i++) { if (nums[i] > maxValue) { maxValue = nums[i]; maxValueIndex = i; } } TreeNode* node = new TreeNode (0 ); node->val = maxValue;
最大值所在的下标左区间 构造左子树
这里要判断maxValueIndex > 0,因为要保证左区间至少有一个数值。
代码如下:
1 2 3 4 if (maxValueIndex > 0 ) { vector<int > newVec (nums.begin(), nums.begin() + maxValueIndex) ; node->left = constructMaximumBinaryTree (newVec); }
最大值所在的下标右区间 构造右子树
判断maxValueIndex < (nums.size() - 1),确保右区间至少有一个数值。
代码如下:
1 2 3 4 if (maxValueIndex < (nums.size () - 1 )) { vector<int > newVec (nums.begin() + maxValueIndex + 1 , nums.end()) ; node->right = constructMaximumBinaryTree (newVec); }
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public TreeNode constructMaximumBinaryTree (int [] nums) { return constructMaximumBinaryTree1(nums, 0 , nums.length); } public TreeNode constructMaximumBinaryTree1 (int [] nums, int leftIndex, int rightIndex) { if (rightIndex - leftIndex < 1 ) { return null ; } if (rightIndex - leftIndex == 1 ) { return new TreeNode (nums[leftIndex]); } int maxIndex = leftIndex; int maxVal = nums[maxIndex]; for (int i = leftIndex + 1 ; i < rightIndex; i++) { if (nums[i] > maxVal){ maxVal = nums[i]; maxIndex = i; } } TreeNode root = new TreeNode (maxVal); root.left = constructMaximumBinaryTree1(nums, leftIndex, maxIndex); root.right = constructMaximumBinaryTree1(nums, maxIndex + 1 , rightIndex); return root; } }
617.合并二叉树※ 建议 :这次是一起操作两个二叉树了, 估计大家也没一起操作过两个二叉树,也不知道该如何一起操作,可以看视频先理解一下。 优先掌握递归。
题目链接: https://leetcode.cn/problems/merge-two-binary-trees/ 文章讲解: https://programmercarl.com/0617.%E5%90%88%E5%B9%B6%E4%BA%8C%E5%8F%89%E6%A0%91.html 视频讲解: https://www.bilibili.com/video/BV1m14y1Y7JK/?vd_source=d0597ba9769fffd49ab31d067e3fe824
题目分析
方案一:递归 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { public TreeNode mergeTrees (TreeNode root1, TreeNode root2) { if (root1 == null && root2 == null ) return null ; TreeNode treeNode = new TreeNode (); if (root1 == null ) { treeNode.val = root2.val; } else if (root2 == null ) { treeNode.val = root1.val; } else { treeNode.val = root1.val + root2.val; } if (root1 == null ) { treeNode.left = mergeTrees(root1, root2.left); treeNode.right = mergeTrees(root1, root2.right); } else if (root2 == null ) { treeNode.left = mergeTrees(root1.left, root2); treeNode.right = mergeTrees(root1.right, root2); } else { treeNode.left = mergeTrees(root1.left, root2.left); treeNode.right = mergeTrees(root1.right, root2.right); } return treeNode; } }
结果 解答成功: 执行耗时:1 ms,击败了14.42% 的Java用户 内存消耗:42.4 MB,击败了55.14% 的Java用户
优化一下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public TreeNode mergeTrees (TreeNode root1, TreeNode root2) { if (root1 == null && root2 == null ) return null ; TreeNode treeNode = new TreeNode (); if (root1 == null ) { treeNode.val = root2.val; } else if (root2 == null ) { treeNode.val = root1.val; } else { treeNode.val = root1.val + root2.val; } if (root1 == null ) { treeNode.left = root2.left; treeNode.right = root2.right; } else if (root2 == null ) { treeNode.left = root1.left; treeNode.right = root1.right; } else { treeNode.left = mergeTrees(root1.left, root2.left); treeNode.right = mergeTrees(root1.right, root2.right); } return treeNode; } }
结果 解答成功: 执行耗时:0 ms,击败了100.00% 的Java用户 内存消耗:42.4 MB,击败了54.30% 的Java用户
代码随想录 https://programmercarl.com/0617.%E5%90%88%E5%B9%B6%E4%BA%8C%E5%8F%89%E6%A0%91.html
思路 如何同时遍历两个二叉树呢?
其实和遍历一个树逻辑是一样的,只不过传入两个树的节点,同时操作。
递归 二叉树使用递归,就要想使用前中后哪种遍历方式?
本题使用哪种遍历都是可以的!
我们下面以前序遍历为例。
动画如下:
那么我们来按照递归三部曲来解决:
确定递归函数的参数和返回值:
首先要合入两个二叉树,那么参数至少是要传入两个二叉树的根节点,返回值就是合并之后二叉树的根节点。
代码如下:
1 TreeNode* mergeTrees (TreeNode* t1, TreeNode* t2) {
确定终止条件:
因为是传入了两个树,那么就有两个树遍历的节点t1 和 t2,如果t1 == NULL 了,两个树合并就应该是 t2 了(如果t2也为NULL也无所谓,合并之后就是NULL)。
反过来如果t2 == NULL,那么两个数合并就是t1(如果t1也为NULL也无所谓,合并之后就是NULL)。
代码如下:
1 2 if (t1 == NULL ) return t2; if (t2 == NULL ) return t1;
确定单层递归的逻辑:
单层递归的逻辑就比较好写了,这里我们重复利用一下t1这个树,t1就是合并之后树的根节点(就是修改了原来树的结构)。
那么单层递归中,就要把两棵树的元素加到一起。
接下来t1 的左子树是:合并 t1左子树 t2左子树之后的左子树。
t1 的右子树:是 合并 t1右子树 t2右子树之后的右子树。
最终t1就是合并之后的根节点。
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 class Solution { public TreeNode mergeTrees (TreeNode root1, TreeNode root2) { if (root1 == null ) return root2; if (root2 == null ) return root1; root1.val += root2.val; root1.left = mergeTrees(root1.left,root2.left); root1.right = mergeTrees(root1.right,root2.right); return root1; } }
迭代法 把两个树的节点同时加入队列进行比较。
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Solution { public TreeNode mergeTrees (TreeNode root1, TreeNode root2) { if (root1 == null ) { return root2; } if (root2 == null ) { return root1; } Stack<TreeNode> stack = new Stack <>(); stack.push(root2); stack.push(root1); while (!stack.isEmpty()) { TreeNode node1 = stack.pop(); TreeNode node2 = stack.pop(); node1.val += node2.val; if (node2.right != null && node1.right != null ) { stack.push(node2.right); stack.push(node1.right); } else { if (node1.right == null ) { node1.right = node2.right; } } if (node2.left != null && node1.left != null ) { stack.push(node2.left); stack.push(node1.left); } else { if (node1.left == null ) { node1.left = node2.left; } } } return root1; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class Solution { public TreeNode mergeTrees (TreeNode root1, TreeNode root2) { if (root1 == null ) return root2; if (root2 ==null ) return root1; Queue<TreeNode> queue = new LinkedList <>(); queue.offer(root1); queue.offer(root2); while (!queue.isEmpty()) { TreeNode node1 = queue.poll(); TreeNode node2 = queue.poll(); node1.val = node1.val + node2.val; if (node1.left != null && node2.left != null ) { queue.offer(node1.left); queue.offer(node2.left); } if (node1.right != null && node2.right != null ) { queue.offer(node1.right); queue.offer(node2.right); } if (node1.left == null && node2.left != null ) { node1.left = node2.left; } if (node1.right == null && node2.right != null ) { node1.right = node2.right; } } return root1; } }
700.二叉搜索树中的搜索※ 建议 :递归和迭代 都可以掌握以下,因为本题比较简单, 了解一下 二叉搜索树的特性
题目链接: https://leetcode.cn/problems/search-in-a-binary-search-tree/ s s 文章讲解: https://programmercarl.com/0700.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E4%B8%AD%E7%9A%84%E6%90%9C%E7%B4%A2.html 视频讲解: https://www.bilibili.com/video/BV1wG411g7sF
题目分析
方案一:递归 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution { public TreeNode searchBST (TreeNode root, int val) { if (root == null ) return null ; if (root.val == val) return root; TreeNode nodeLeft = searchBST(root.left, val); TreeNode nodeRight = searchBST(root.right, val); if (nodeLeft != null ) { return nodeLeft; } return nodeRight; } }
结果 解答成功: 执行耗时:0 ms,击败了100.00% 的Java用户 内存消耗:43.4 MB,击败了5.06% 的Java用户
代码随想录 https://programmercarl.com/0700.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E4%B8%AD%E7%9A%84%E6%90%9C%E7%B4%A2.html
思路 二叉搜索树是一个有序树:
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉搜索树
这就决定了,二叉搜索树,递归遍历和迭代遍历和普通二叉树都不一样。
本题,其实就是在二叉搜索树中搜索一个节点。那么我们来看看应该如何遍历
递归法
确定递归函数的参数和返回值
递归函数的参数传入的就是根节点和要搜索的数值,返回的就是以这个搜索数值所在的节点。
代码如下:
1 TreeNode* searchBST (TreeNode* root, int val)
确定终止条件
如果root为空,或者找到这个数值了,就返回root节点。
1 if (root == NULL || root->val == val) return root;
确定单层递归的逻辑
看看二叉搜索树的单层递归逻辑有何不同。
因为二叉搜索树的节点是有序的,所以可以有方向的去搜索。
如果root->val > val,搜索左子树,如果root->val < val,就搜索右子树,最后如果都没有搜索到,就返回NULL。
代码如下:
1 2 3 4 TreeNode* result = NULL ;if (root->val > val) result = searchBST (root->left, val);if (root->val < val) result = searchBST (root->right, val);return result;
很多录友写递归函数的时候 习惯直接写 searchBST(root->left, val)
,却忘了 递归函数还有返回值。
递归函数的返回值是什么? 是 左子树如果搜索到了val,要将该节点返回。 如果不用一个变量将其接住,那么返回值不就没了。
所以要 result = searchBST(root->left, val)
。
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public TreeNode searchBST (TreeNode root, int val) { if (root == null || root.val == val) { return root; } TreeNode left = searchBST(root.left, val); if (left != null ) { return left; } return searchBST(root.right, val); } }class Solution { public TreeNode searchBST (TreeNode root, int val) { if (root == null || root.val == val) { return root; } if (val < root.val) { return searchBST(root.left, val); } else { return searchBST(root.right, val); } } }
迭代法 一提到二叉树遍历的迭代法,可能立刻想起使用栈来模拟深度遍历,使用队列来模拟广度遍历。
对于二叉搜索树可就不一样了,因为二叉搜索树的特殊性,也就是节点的有序性,可以不使用辅助栈或者队列就可以写出迭代法。
对于一般二叉树,递归过程中还有回溯的过程,例如走一个左方向的分支走到头了,那么要调头,在走右分支。
而对于二叉搜索树,不需要回溯的过程,因为节点的有序性就帮我们确定了搜索的方向。
例如要搜索元素为3的节点,我们不需要搜索其他节点,也不需要做回溯,查找的路径已经规划好了。
中间节点如果大于3就向左走,如果小于3就向右走,如图:
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Solution { public TreeNode searchBST (TreeNode root, int val) { if (root == null || root.val == val) { return root; } Stack<TreeNode> stack = new Stack <>(); stack.push(root); while (!stack.isEmpty()) { TreeNode pop = stack.pop(); if (pop.val == val) { return pop; } if (pop.right != null ) { stack.push(pop.right); } if (pop.left != null ) { stack.push(pop.left); } } return null ; } }class Solution { public TreeNode searchBST (TreeNode root, int val) { while (root != null ) if (val < root.val) root = root.left; else if (val > root.val) root = root.right; else return root; return null ; } }
98.验证二叉搜索树※ 建议 :遇到 搜索树,一定想着中序遍历,这样才能利用上特性。
但本题是有陷阱的,可以自己先做一做,然后在看题解,看看自己是不是掉陷阱里了。这样理解的更深刻。
题目链接: https://leetcode.cn/problems/validate-binary-search-tree/ 文章讲解: https://programmercarl.com/0098.%E9%AA%8C%E8%AF%81%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91.html 视频讲解: https://www.bilibili.com/video/BV18P411n7Q4
题目分析
方案一:递归 需要进行一些特殊判断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 class Solution { public boolean isValidBST (TreeNode root) { if (root == null ) return true ; if (root.left == null && root.right == null ) return true ; TreeNode nodeLeft = root.left; TreeNode nodeRight = root.right; if (nodeLeft == null ) { if (root.val >= nodeRight.val) return false ; } else if (nodeRight == null ) { if (nodeLeft.val >= root.val) return false ; } else { if (nodeLeft.val >= root.val || root.val >= nodeRight.val) return false ; } TreeNode nodeLeftDepth = root.left; TreeNode nodeRightDepth = root.right; if (nodeLeftDepth != null ) { while (nodeLeftDepth.right != null ) { nodeLeftDepth = nodeLeftDepth.right; } } if (nodeRightDepth != null ) { while (nodeRightDepth.left != null ) { nodeRightDepth = nodeRightDepth.left; } } if (nodeLeftDepth == null ) { if (root.val >= nodeRightDepth.val) return false ; } else if (nodeRightDepth == null ) { if (nodeLeftDepth.val >= root.val) return false ; } else { if (nodeLeftDepth.val >= root.val || root.val >= nodeRightDepth.val) return false ; } boolean boolLeft = isValidBST(nodeLeft); boolean boolRight = isValidBST(nodeRight); return boolLeft && boolRight; } }
结果 解答成功: 执行耗时:0 ms,击败了100.00% 的Java用户 内存消耗:42.7 MB,击败了46.83% 的Java用户
代码随想录 https://programmercarl.com/0098.%E9%AA%8C%E8%AF%81%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91.html
思路 要知道中序遍历下,输出的二叉搜索树节点的数值是有序序列。
有了这个特性,验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了
递归法 可以递归中序遍历将二叉搜索树转变成一个数组,代码如下:
1 2 3 4 5 6 7 vector<int > vec;void traversal (TreeNode* root) { if (root == NULL ) return ; traversal (root->left); vec.push_back (root->val); traversal (root->right); }
然后只要比较一下,这个数组是否是有序的,注意二叉搜索树中不能有重复元素 。
1 2 3 4 5 6 traversal (root);for (int i = 1 ; i < vec.size (); i++) { if (vec[i] <= vec[i - 1 ]) return false ; }return true ;
整体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution {private : vector<int > vec; void traversal (TreeNode* root) { if (root == NULL ) return ; traversal (root->left); vec.push_back (root->val); traversal (root->right); }public : bool isValidBST (TreeNode* root) { vec.clear (); traversal (root); for (int i = 1 ; i < vec.size (); i++) { if (vec[i] <= vec[i - 1 ]) return false ; } return true ; } };
以上代码中,我们把二叉树转变为数组来判断,是最直观的,但其实不用转变成数组,可以在递归遍历的过程中直接判断是否有序。
这道题目比较容易陷入两个陷阱:
不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了 。
写出了类似这样的代码:
1 2 3 4 5 if (root->val > root->left->val && root->val < root->right->val) { return true ; } else { return false ; }
我们要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点 。所以以上代码的判断逻辑是错误的。
例如: [10,5,15,null,null,6,20] 这个case:
节点10大于左节点5,小于右节点15,但右子树里出现了一个6 这就不符合了!
样例中最小节点 可能是int的最小值,如果这样使用最小的int来比较也是不行的。
此时可以初始化比较元素为longlong的最小值。
问题可以进一步演进:如果样例中根节点的val 可能是longlong的最小值 又要怎么办呢?文中会解答。
了解这些陷阱之后我们来看一下代码应该怎么写:
递归三部曲:
要定义一个longlong的全局变量,用来比较遍历的节点是否有序,因为后台测试数据中有int最小值,所以定义为longlong的类型,初始化为longlong最小值。
注意递归函数要有bool类型的返回值, 我们在二叉树:递归函数究竟什么时候需要返回值,什么时候不要返回值? (opens new window) 中讲了,只有寻找某一条边(或者一个节点)的时候,递归函数会有bool类型的返回值。
其实本题是同样的道理,我们在寻找一个不符合条件的节点,如果没有找到这个节点就遍历了整个树,如果找到不符合的节点了,立刻返回。
代码如下:
1 2 long long maxVal = LONG_MIN; bool isValidBST (TreeNode* root)
如果是空节点 是不是二叉搜索树呢?
是的,二叉搜索树也可以为空!
代码如下:
1 if (root == NULL ) return true ;
中序遍历,一直更新maxVal,一旦发现maxVal >= root->val,就返回false,注意元素相同时候也要返回false。
代码如下:
1 2 3 4 5 6 7 8 bool left = isValidBST (root->left); if (maxVal < root->val) maxVal = root->val; else return false ;bool right = isValidBST (root->right); return left && right;
整体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution {public : long long maxVal = LONG_MIN; bool isValidBST (TreeNode* root) { if (root == NULL ) return true ; bool left = isValidBST (root->left); if (maxVal < root->val) maxVal = root->val; else return false ; bool right = isValidBST (root->right); return left && right; } };
以上代码是因为后台数据有int最小值测试用例,所以都把maxVal改成了longlong最小值。
如果测试数据中有 longlong的最小值,怎么办?
不可能在初始化一个更小的值了吧。 建议避免 初始化最小值,如下方法取到最左面节点的数值来比较。
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { TreeNode max; public boolean isValidBST (TreeNode root) { if (root == null ) { return true ; } boolean left = isValidBST(root.left); if (!left) { return false ; } if (max != null && root.val <= max.val) { return false ; } max = root; boolean right = isValidBST(root.right); return right; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { public boolean isValidBST (TreeNode root) { return validBST(Long.MIN_VALUE, Long.MAX_VALUE, root); } boolean validBST (long lower, long upper, TreeNode root) { if (root == null ) return true ; if (root.val <= lower || root.val >= upper) return false ; return validBST(lower, root.val, root.left) && validBST(root.val, upper, root.right); } }class Solution { private long prev = Long.MIN_VALUE; public boolean isValidBST (TreeNode root) { if (root == null ) { return true ; } if (!isValidBST(root.left)) { return false ; } if (root.val <= prev) { return false ; } prev = root.val; return isValidBST(root.right); } }
迭代法 可以用迭代法模拟二叉树中序遍历
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { public boolean isValidBST (TreeNode root) { Stack<TreeNode> stack = new Stack <>(); TreeNode pre = null ; if (root != null ) stack.add(root); while (!stack.isEmpty()){ TreeNode curr = stack.peek(); if (curr != null ){ stack.pop(); if (curr.right != null ) stack.add(curr.right); stack.add(curr); stack.add(null ); if (curr.left != null ) stack.add(curr.left); }else { stack.pop(); TreeNode temp = stack.pop(); if (pre != null && pre.val >= temp.val) return false ; pre = temp; } } return true ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution { public boolean isValidBST (TreeNode root) { if (root == null ) { return true ; } Stack<TreeNode> stack = new Stack <>(); TreeNode pre = null ; while (root != null || !stack.isEmpty()) { while (root != null ) { stack.push(root); root = root.left; } TreeNode pop = stack.pop(); if (pre != null && pop.val <= pre.val) { return false ; } pre = pop; root = pop.right; } return true ; } }