【剑指offer】23.二叉搜索树的后序遍历序列
总目录:
1.问题描述
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回 true ,否则返回 false 。假设输入的数组的任意两个数字都互不相同。
 数据范围: 节点数量 0≤n≤1000 ,节点上的值满足 1≤val≤10^5,保证节点上的值各不相同
要求:空间复杂度 O(n),时间时间复杂度 O(n^2)
要求:空间复杂度 O(n),时间时间复杂度 O(n^2)
提示: 
  1.二叉搜索树是指父亲节点大于左子树中的全部节点,但是小于右子树中的全部节点的树。 
  2.该题我们约定空树不是二叉搜索树 
  3.后序遍历是指按照 “左子树-右子树-根节点” 的顺序遍历 
  4.二叉搜索树不是满树,除根节点外可以任意空缺子节点;
2.问题分析
1递归,注意各种边界条件
3.代码实例
递归
 
1 class Solution { 2 public: 3 bool IsBST(vector<int> sequence) { 4 int sequenceSize = sequence.size(); 5 6 //中止条件 7 //小于等于一个节点 8 if (sequenceSize <= 1) { 9 return true; 10 } 11 12 //寻找左右子树分割点 13 int rootVal = sequence[sequenceSize - 1]; 14 int rightRootId = sequenceSize - 1;//最大到根节点处 15 for (int i = 0; i < sequenceSize; i++) { 16 if (sequence[i] > rootVal) { 17 rightRootId = i; 18 break; 19 } 20 } 21 //切割子树 22 vector<int> leftVec, rightVec; 23 for (int i = 0; i < rightRootId; i++) { 24 leftVec.push_back(sequence[i]); 25 } 26 for (int i = rightRootId; i < sequenceSize - 1; i++) { 27 rightVec.push_back(sequence[i]); 28 } 29 30 //检查根、左右子节点的大小关系 31 int leftSize = leftVec.size(); 32 if (leftSize >= 1) { 33 for (int i = 0; i < leftSize; i++) { 34 if (leftVec[i] >= rootVal) { 35 return false; 36 } 37 } 38 } 39 bool isLeftBe = IsBST(leftVec); 40 41 int rightSize = rightVec.size(); 42 if (rightSize >= 1) { 43 for (int i = 0; i < rightSize; i++) { 44 if (rightVec[i] <= rootVal) { 45 return false; 46 } 47 } 48 } 49 bool isRightBe = IsBST(rightVec); 50 51 //递归调用 52 return isLeftBe && isRightBe; 53 } 54 55 bool VerifySquenceOfBST(vector<int> sequence) { 56 int sequenceSize = sequence.size(); 57 58 //中止条件 59 //空树不是搜索树 60 if (sequenceSize <= 0) { 61 return false; 62 } 63 64 //递归调用 65 return IsBST(sequence); 66 } 67 };
优雅的递归,不要那么多vector操作
 
1 class Solution { 2 public: 3 bool VerifySquenceOfBST(vector<int> sequence) { 4 int n = sequence.size(); 5 if(n == 0) return false; // 注意审题, 约定空树不是二叉搜索树 6 return check(sequence, 0, n - 1); 7 } 8 9 bool check(vector<int>& sequence, int l, int r){ 10 if(l >= r) return true; // 若当前子树只有一个节点 11 12 int root = sequence[r]; // 当前子树的根节点 13 14 // 划分出右子树 15 int j = r - 1; 16 while(j >= 0 && sequence[j] > root) j--; 17 18 // 检查左子树是不是存在大于根节点的数 19 for(int i = l; i <= j; i++){ 20 if(sequence[i] > root) return false; 21 } 22 23 // 分治法检查左子树和右子树 24 return check(sequence, l, j) && check(sequence, j + 1, r - 1); 25 } 26 };
 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号