包含min函数的栈、栈的压入弹出序列、从上往下打印二叉树、二叉搜索树的后序遍历序列

本文介绍了栈的几种应用场景,包括实现带有min函数的栈,判断栈的压入弹出序列是否合法,以及二叉树的从上往下打印和二叉搜索树的后序遍历序列的验证。通过具体的代码实现,阐述了栈的规则性设计和二叉树的层序遍历与后序遍历策略。解题思路详细,适合加深对数据结构和算法的理解。

1、包含min函数的栈

本题考点: 栈的规则性设计 牛客链接

题目描述:
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的 min 函数,输入操作时保证 pop、top 和 min 函数操作时,栈中一定有元素。

此栈包含的方法有:
push(value):将value压入栈中
pop():弹出栈顶元素
top():获取栈顶元素
min():获取栈中最小元素

数据范围:操作数量满足0≤n≤300 ,输入的元素满足∣val∣≤10000
进阶:栈的各个操作的时间复杂度是O(1) ,空间复杂度是O(n)

解题思路:

在这里插入图片描述

代码:

class Solution {
private:
    stack<int> data_stack;
    stack<int> min_stack;
public:
    void push(int value) {
        data_stack.push(value);
        if(min_stack.empty() || value < min_stack.top())
        {
            min_stack.push(value);
        }
        else // !min_stack.empty() && value >= min_stack.top()
        {
            min_stack.push(min_stack.top());
        }
    }
    void pop() {
        data_stack.pop();
        min_stack.pop();
    }
    int top() {
        return data_stack.top();
    }
    int min() {
        return min_stack.top();
    }
};

2、栈的压入弹出序列

本题考点: 栈的理解 牛客链接

题目描述:
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。

  1. 0<=pushV.length == popV.length <=1000
  2. -1000<=pushV[i]<=1000
  3. pushV 的所有数字均不相同

解题思路:

在这里插入图片描述

代码:

class Solution {
public:
    bool IsPopOrder(vector<int> pushV,vector<int> popV) {
        
        int pushi= 0, popj = 0;
        stack<int> st;
        while(pushi < pushV.size()) 
        {
            st.push(pushV[pushi++]);
            while(!st.empty() && st.top() == popV[popj])
            {
                st.pop();
                popj++;
            }  
        }
        return st.empty();
        //return pushi == pushV.size();
    }
};

3、从上往下打印二叉树

本题考点: 二叉树层序遍历 牛客链接

题目描述:
不分行从上往下打印出二叉树的每个节点,同层节点从左至右打印。例如输入{8,6,10,#,#,2,1},如以下图中的示例二叉树,则依次打印8,6,10,2,1(空节点不打印,跳过),请你将打印的结果存放到一个数组里面,返回。
数据范围:
0<=节点总数<=1000
-1000<=节点值<=1000
在这里插入图片描述
解题思路:

在这里插入图片描述

代码:

class Solution {
public:
    vector<int> PrintFromTopToBottom(TreeNode* root) {
		vector<int> result;
		if(root == nullptr)
			return result;

		queue<TreeNode*> qe;
		qe.push(root);
		while(!qe.empty())
		{
			TreeNode* front = qe.front();
			qe.pop();
			result.push_back(front->val);

			if(front->left != nullptr) //左子树不为空将左子树入队列
				qe.push(front->left);
			if(front->right != nullptr)//右子树不为空将右子树入队列
				qe.push(front->right);
		}
		return result;
    }
};

4、二叉搜索树的后序遍历序列

本题考点: BST特征的理解 牛客链接

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

数据范围: 节点数量 0≤n≤1000 ,节点上的值满足1≤val≤10^5 ,保证节点上的值各不相同
要求:空间复杂度O(n) ,时间时间复杂度 O(n^2)

提示:
1.二叉搜索树是指父亲节点大于左子树中的全部节点,但是小于右子树中的全部节点的树。
2.该题我们约定空树不是二叉搜索树
3.后序遍历是指按照 “左子树-右子树-根节点” 的顺序遍历

解题思路:

  • 二叉搜索树:它或者是一棵空树,或者是具有下列性质的二叉树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

  • 后序遍历:先左后右再根

  • BST的后序序列的合法序列是,对于一个序列S,最后一个元素是x(也就是root节点),如果去掉最后一个元素的序列为T,那么T满足:T可以分成两段,前一段(左子树)小于x,后一段(右子树)大于x,且这两段(子树)都是合法的后序序列

  • 验证思路就是:当前序列,及其子序列必须都满足上述定义

在这里插入图片描述

代码:

class Solution {
public:

    bool _VerifySquenceOfBST(vector<int>& v, int begin, int end)
    {

        //返回条件
        if(begin >= end)
        {
            //区间是在不断缩小到,走到这里说明之前的范围满足检测条件
            return true;
        }
        
        //判断逻辑
        int root = v[end];
        int i = begin;
        while(i < end && v[i] < v[end])
        {
            i++;
        }
        for(int j = i; j < end; j++)
        {
            if(v[j] < v[end])
                return false;
        }

        return _VerifySquenceOfBST(v, begin, i - 1) && _VerifySquenceOfBST(v, i, end - 1);
    }
    bool VerifySquenceOfBST(vector<int> sequence) {
        if(sequence.empty())
            return false;
        
        return _VerifySquenceOfBST(sequence, 0, sequence.size() - 1);
    }
};
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小朱同学..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值