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
參考資料:
https://leetcode.com/problems/verify-preorder-sequence-in-binary-search-tree/