[LeetCode] 255. Verify Preorder Sequence in Binary Search Tree 驗證二叉搜索樹的先序序列

 

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

You may assume each number in the sequence is unique.git

Consider the following binary search tree: github

     5
    / \
   2   6
  / \
 1   3

Example 1:數組

Input: [5,2,6,1,3]
Output: false

Example 2:ide

Input: [5,2,1,3,6]
Output: true

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

 

這道題讓給了一個一維數組,讓咱們驗證其是否爲一個二叉搜索樹的先序遍歷出的順序,二叉搜索樹的性質是左<根<右,若是用中序遍歷獲得的結果就是有序數組,而先序遍歷的結果就不是有序數組了,可是難道一點規律都沒有了嗎,其實規律仍是有的,根據二叉搜索樹的性質,當前節點的值必定大於其左子樹中任何一個節點值,並且其右子樹中的任何一個節點值都不能小於當前節點值,能夠用這個性質來驗證,舉個例子,好比下面這棵二叉搜索樹:post

 

     5
    / \
   2   6
  / \
 1   3

 

其先序遍歷的結果是 {5, 2, 1, 3, 6},先設一個最小值 low,而後遍歷數組,若是當前值小於這個最小值 low,返回 false,對於根節點,將其壓入棧中,而後日後遍歷,若是遇到的數字比棧頂元素小,說明是其左子樹的點,繼續壓入棧中,直到遇到的數字比棧頂元素大,那麼就是右邊的值了,須要找到是哪一個節點的右子樹,因此更新 low 值並刪掉棧頂元素,而後繼續和下一個棧頂元素比較,若是仍是大於,則繼續更新 low 值和刪掉棧頂,直到棧爲空或者當前棧頂元素大於當前值中止,壓入當前值,這樣若是遍歷完整個數組以前都沒有返回 false 的話,最後返回 true 便可,參見代碼以下:url

 

解法一:spa

class Solution {
public:
    bool verifyPreorder(vector<int>& preorder) {
        int low = INT_MIN;
        stack<int> s;
        for (auto a : preorder) {
            if (a < low) return false;
            while (!s.empty() && a > s.top()) {
                low = s.top(); s.pop();
            }
            s.push(a);
        }
        return true;
    }
};

 

下面這種方法和上面的思路相同,爲了使空間複雜度爲常量,咱們不能使用 stack,因此直接修改 preorder,將 low 值存在 preorder 的特定位置便可,前提是不能影響當前的遍歷,參見代碼以下:code

 

解法二:

class Solution {
public:
    bool verifyPreorder(vector<int>& preorder) {
        int low = INT_MIN, i = -1;
        for (auto a : preorder) {
            if (a < low) return false;
            while (i >= 0 && a > preorder[i]) {
                low = preorder[i--];
            }
            preorder[++i] = a;
        }
        return true;
    }
};

 

下面這種方法使用了分治法,跟以前那道驗證二叉搜索樹的題 Validate Binary Search Tree 的思路很相似,在遞歸函數中維護一個下界 lower 和上界 upper,那麼當前遍歷到的節點值必須在 (lower, upper) 區間以內,而後在給定的區間內搜第一個大於當前節點值的點,以此爲分界,左右兩部分分別調用遞歸函數,注意左半部分的 upper 更新爲當前節點值 val,代表左子樹的節點值都必須小於當前節點值,而右半部分的遞歸的 lower 更新爲當前節點值 val,代表右子樹的節點值都必須大於當前節點值,若是左右兩部分的返回結果均爲真,則總體返回真,參見代碼以下:

 

解法三:

class Solution {
public:
    bool verifyPreorder(vector<int>& preorder) {
        return helper(preorder, 0, preorder.size() - 1, INT_MIN, INT_MAX);
    }
    bool helper(vector<int>& preorder, int start, int end, int lower, int upper) {
        if (start > end) return true;
        int val = preorder[start], i = 0;
        if (val <= lower || val >= upper) return false;
        for (i = start + 1; i <= end; ++i) {
            if (preorder[i] >= val) break;
        }
        return helper(preorder, start + 1, i - 1, lower, val) && helper(preorder, i, end, val, upper);
    }
};

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/255

 

相似題目:

Binary Tree Preorder Traversal

Validate Binary Search Tree

 

參考資料:

https://leetcode.com/problems/verify-preorder-sequence-in-binary-search-tree/

https://leetcode.com/problems/verify-preorder-sequence-in-binary-search-tree/discuss/68142/Java-O(n)-and-O(1)-extra-space

https://leetcode.com/problems/verify-preorder-sequence-in-binary-search-tree/discuss/68185/C%2B%2B-easy-to-understand-solution-with-thought-process-and-detailed-explanation

 

LeetCode All in One 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索