《leetcode》剑指 Offer 33. 二叉搜索树的后序遍历序列《单调栈》

18 篇文章 0 订阅

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

难度中等253

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

 

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

     5
    / \
   2   6
  / \
 1   3

示例 1:

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

示例 2:

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

 

提示:

  1. 数组长度 <= 1000

思路:

1.单调栈,

2.递归分治

3.中序后序判断树

 

Code1:单调栈 (O(N),O(N))

class Solution {
    public boolean verifyPostorder(int[] postorder) {
       Deque<Integer>stack=new LinkedList<Integer>();
       int root=Integer.MAX_VALUE;
       //O(n) O(n)
       //逆序 根右左 先增后减 所以可以用单调栈
        for(int i=postorder.length-1;i>=0;i--)
        {
            if(postorder[i]>root) return false;
            while(!stack.isEmpty()&&stack.peek()>postorder
            [i])//开始递减的时候要更新root;
            {
                root=stack.pop();
            }
            stack.push(postorder[i]);
        }
        return true;
    }
}

Code2:递归分治(O(N^2),O(N))

class Solution {
    public boolean verifyPostorder(int[] postorder) {
        return recur(postorder, 0, postorder.length - 1);
    }

    //根据后序遍历的特点 分治来算 O(N^2) O(N)
    boolean recur(int[] postorder, int i, int j) {
        if(i >= j) return true;
        int p = i;
        while(postorder[p] < postorder[j]) p++;//左子树
        int m = p;
        while(postorder[p] > postorder[j]) p++;//右子树
        return p == j && recur(postorder, i, m - 1) && recur(postorder, m, j - 1);
    }
}

Code3:中序后序判断树(O(N^2),O(N))

class Solution {
    //中序遍历+后序遍历 确定树 O(n^2) O(n)
    HashMap<Integer,Integer>map;
    public boolean isOk(int mid[],int post[],int s1,int e1,int s2,int e2)
    {
       int rootId=map.get(post[e2]);
       for(int i=s2;i<s2+rootId-s1;i++)
       {
           if(post[i]>post[e2])
                return false;
       }
       for(int i=s2+rootId-s1;i<e2;i++)
       {
           if(post[i]<post[e2])
                return false;
       }
       if(rootId-1<=s1&&e1>rootId+1)//左子树ok 遍历右子树
        return isOk(mid,post,rootId+1,e1,s2+rootId-s1,e2-1);
       if(rootId-1>s1&&e1<=rootId+1)//右子树ok 遍历左子树
        return isOk(mid,post,s1,rootId-1,s2,s2+rootId-1-s1);
       if(rootId-1<=s1&&e1<=rootId+1)//左右子树都ok
            return true;
       return isOk(mid,post,s1,rootId-1,s2,s2+rootId-1-s1)&&isOk(mid,post,rootId+1,e1,s2+rootId-s1,e2-1);
    } 
    public boolean verifyPostorder(int[] postorder) {
        int n=postorder.length;
        if(n<2) return true;
        int midorder[]=new int[n];
        for(int i=0;i<n;i++)
            midorder[i]=postorder[i];
        Arrays.sort(midorder);
        map=new HashMap<>();
        for(int i=0;i<n;i++)
            map.put(midorder[i],i);
        return isOk(midorder,postorder,0,n-1,0,n-1);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值