(树) 剑指 Offer 33. 二叉搜索树的后序遍历序列 ——【Leetcode每日一题】

❓剑指 Offer 33. 二叉搜索树的后序遍历序列

难度:中等

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。

参考以下这颗二叉搜索树:

     5
    / \
   2   6
  / \
 1   3

示例 1:

输入: [1,6,3,2,5]
输出: false

示例 2:

输入: [1,3,2,6,5]
输出: true

提示

  • 数组长度 <= 1000

思路:递归

后序遍历前序遍历 的特点一样,唯一不同的就是根结点一个在前,一个在后!

又有二叉搜索树的性质,二叉搜索树是有序的,对每一个树:

  • 左子树上所有结点的值都 小于 根节点的值;
  • 右子树上所有结点的值都 大于 根节点的值。

所以只要知道 根节点 就能确定哪些结点属于左子树,哪些属于右子树;而后序遍历刚好能得到根节点

  • 所以先拿到序列的最后一个数,即为 根结点
  • 然后根据 二叉搜索树的性质,找到左右子树的分界点 flag
    • 从后往前遍历,找到第一个小于根节点的数,即为分界点flag
    • 分界点 flag 及其左边的应该都在左子树,左子树都应小于根节点,如果有不小于的根节点的数,则一定不是二叉搜索树,返回 false
    • 如果分界点左边的数都小于根节点,则根据 分界点 flag 切成两部分,左子树右子树,再分别判断,只有同时都是二叉搜索树时,才返回 true

代码:(C++、Java)

C++

class Solution {
public:
    bool verifyPostorder(vector<int>& postorder) {
        if(postorder.size() == 0) return true;
        return verify(postorder, 0, postorder.size() - 1);
    }
    bool verify(vector<int>& postorder, int fir, int lst){
        if(fir >= lst) return true;
        int flag = lst - 1;
        while(flag >= fir && postorder[flag] > postorder[lst]){
            flag--;
        }
        for(int i = flag - 1; i >= fir; i--){
            if(postorder[i] > postorder[lst]) return false;
        }
        return verify(postorder, fir, flag) && verify(postorder, flag + 1, lst -1);
    }
};

Java

class Solution {
    public boolean verifyPostorder(int[] postorder) {
        if(postorder.length == 0) return true;
        return verify(postorder, 0, postorder.length - 1);
    }
    private boolean verify(int[] postorder, int fir, int lst){
        if(fir >= lst) return true;
        int flag = lst - 1;
        while(flag >= fir && postorder[flag] > postorder[lst]){
            flag--;
        }
        for(int i = flag - 1; i >= fir; i--){
            if(postorder[i] > postorder[lst]) return false;
        }
        return verify(postorder, fir, flag) && verify(postorder, flag + 1, lst - 1);
    }
}

运行结果:

(树) 剑指 Offer 33. 二叉搜索树的后序遍历序列 ——【Leetcode每日一题】_第1张图片

复杂度分析:

  • 时间复杂度 O ( n 2 ) O(n^2) O(n2),每次调用 verify 减去一个根节点,最差该二叉树退化为链表,递归调用了 n 次,且比较了 n 次。
  • 空间复杂度 O ( n ) O(n) O(n),递归调用栈,最差该二叉树退化为链表,深度为 n

题目来源:力扣。

放弃一件事很容易,每天能坚持一件事一定很酷,一起每日一题吧!
关注我LeetCode主页 / CSDN—力扣专栏,每日更新!

注: 如有不足,欢迎指正!

你可能感兴趣的:(LeetCode,leetcode,算法,数据结构)