Leetcode: Verify Preorder Sequence in Binary Search Tree

本文介绍了一种验证数组是否为有效二叉搜索树前序遍历的方法,通过递归检查左右子树元素的合法性,并提供两种优化方案:一种使用栈实现O(N)时间复杂度和O(H)空间复杂度;另一种采用原地替换数组元素的方式达到常数级空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given an array of numbers, verify whether it is the correct preorder traversal sequence of a binary search tree.

You may assume each number in the sequence is unique.

Follow up:
Could you do it using only constant space complexity?

           4

        /     \

      2         6

    /   \      /   \

  1     3   5      7

如图所示BST, preorder结果是 4 2 1 3 6 5 7

4是root, 213是左子树,657是右子树

idea就是右子树不能再出现比root小的数,一旦出现,return false. 这样一层一层recursion, 直到子树只剩一个node, return true

 1 public class Solution {
 2     public boolean verifyPreorder(int[] preorder) {
 3         if(preorder==null || preorder.length==0) return true;
 4         return helper(0, preorder.length-1, preorder);
 5     }
 6     
 7     public boolean helper(int l, int r, int[] preorder) {
 8         if (l >= r) return true;
 9         int root = l;
10         int right = l-1;
11         boolean found = false;
12         for (int i=l+1; i<=r; i++) {
13             if (preorder[i] > preorder[root]) { //found right subtree 1st node
14                 if (!found) {
15                     found = true;
16                     right = i;
17                 }
18             }
19             else {
20                 if (found) return false;
21             }
22         }
23         if (!found) return helper(root+1, r, preorder);
24         else return helper(root+1, right-1, preorder) && helper(right, r, preorder);
25     }
26 }

这样时间代价很大

更好的方法,参考https://leetcode.com/discuss/51543/java-o-n-and-o-1-extra-space

Time: O(N), Space: O(H)

imulate the traversal, keeping a stack of nodes. If the next number is smaller than the last stack value, then we're still in the left subtree of all stack nodes, so just push the new one onto the stack. Otherwise, pop all smaller ancestor values, as we must now be in their right subtrees (or even further, in the right subtree of an ancestor). Also, use the popped values as a lower bound, since being in their right subtree means we must never come across a smaller number anymore.

 1 public boolean verifyPreorder(int[] preorder) {
 2     int low = Integer.MIN_VALUE;
 3     Stack<Integer> path = new Stack();
 4     for (int p : preorder) {
 5         if (p < low)
 6             return false;
 7         while (!path.empty() && p > path.peek())
 8             low = path.pop();
 9         path.push(p);
10     }
11     return true;
12 }

Solution 2 ... O(1) extra space

Same as above, but use the given array as the stack. i refer to the stack.top.next

 1 public boolean verifyPreorder(int[] preorder) {
 2     int low = Integer.MIN_VALUE, i = 0;
 3     for (int p : preorder) {
 4         if (p < low)
 5             return false;
 6         while (i > 0 && p > preorder[i-1])
 7             low = preorder[--i];
 8         preorder[i++] = p;
 9     }
10     return true;
11 }

 i refer to stack.top

 1 public boolean verifyPreorder(int[] preorder) {
 2     int low = Integer.MIN_VALUE, i = -1;
 3     for (int p : preorder) {
 4         if (p < low)
 5             return false;
 6         while (i >= 0 && p > preorder[i])
 7             low = preorder[i--];
 8         preorder[++i] = p;
 9     }
10     return true;
11 }

 

转载于:https://www.cnblogs.com/EdwardLiu/p/5066035.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值