牛客网常见算法思路 (四)栈和队列

案例一

实现一个特殊的栈,增加一个需求,可以返回栈中最小元素操作
方法一:
弄两个栈一个栈放正常的 第二个放最小的 只有当前数字小于等于stackMin栈顶时才压入
方法二:
弄两个栈一个栈放正常的 第二个放最小的,当前数字大于stackMin时也压入不过压入荡秋千前stackMin栈顶(相当于重复一次),记录了每一步的最小值
方法一二:前者省空间花时间

案例二

编写一个类,只能用两个栈结构实现队列,支持队列基本操作add poll peek
StackPush和StackPop,一个StackPush栈进,一个StackPop栈出,进的栈StackPush将元素倒入StackPop
注意两点:要一次性将数据全部倒入,切倒入时StackPop要为空

案例三

实现一个栈的逆序,但只能用递归函数和栈本身操作来实现,不能申请额外的数据结构

//移除占地元素并返回,
public int get(Stack<Integer> stack){
    int result = stack.pop();//取本层栈顶1
    if(stack.isEmpty()){
        return result;//如果是最后一层,直接弹出
    }else{
        int last = get(stack);//进入下一层
        stack.push(result);//不是最后一层,取出后再push进栈
        return last;
    }
}


//把栈底元素删除并返回的功能,把栈中元素逆序的主方法
public void reverse(Stack<Integer> stack){
    if(stack.isEmpty()){
        return;
    }
    int i =get(stack);//上一个方法
    reverse(stack);
    stack.push(i)
}

案例四

一个栈中元素类型为整型,想将该栈从顶到底排序,只许申请一个栈,可以申请新变量,但不能申请额外数据结构

排序栈Stack 申请的辅助栈help,Stack弹出一个数到help,若该数小于等于help当前栈顶,直接压入;反之则将help依次弹出并压入Stack中,知道出现小于等于当前栈顶

案例五

一个整型数组arr和一个大小为w的窗口数组从左滑到右,每次滑一个单位,返回一个长度为n-w+1的数组res,res[i]为当前窗口驻足中的最大值
例子:
[4,3,5,4,3,3,4,7],w=3,第一个窗口[4,3,5],返回5,第二个窗口[3,5,4],返回5,如此类推返回[5,5,5,4,6,7]
普通解法时间复杂度O(N*w),每次对一个窗口遍历w个数,选出最大值
最优解O(N),利用双端队列qMax{},存放数组下标
假设arr[i],放入规则为:
1、若为空直接放
2、若不为空, 取出qMax队尾存放下标 j ,如果arr[j]> arr[i]直接将i放到qmax队尾,否则一直从qmax队尾弹出下标,知道某个下标在qmax中对应的值大于arr[i],把arr[i]放入qmax队尾,
弹出规则
1、如果qmax队头下标=i-w,弹出队头下标,res取对应值即可
此时qmax成为维护长度为w的结构

总结:1、队列里的数大,读取的数放最后;队列里的数小等,弹出滚蛋,读取的数进来
2、定时筛选掉移出滑动窗口以外的数

案例六

给定一个没有重复元素的数组arr,写出生成这个数组的MaxTree的函数。要求如果数组长度为N,时间空间复杂度O(N)
MaxTree概念:二叉树,数组的每一个值对应二叉树节点,所有子树在内(包括本身),值最大的节点都是树的头
设 3 4 5 1 2,设置两边子树,“左边第一个大的数”,“右边第一个大的数”
3,左边第一个比3大的数null,右边第一个比3大的数4
4,左边第一个比4大的数null,右边第一个比4大的数5
5,左边第一个比5大的数null,右边第一个比5大的数null
1,左边第一个比1大的数5 ,右边第一个比1大的数2
2,左边第一个比2大的数5 ,右边第一个比2大的数null
每个数的父节点是"左边第一个大的数","右边第一个大的数"中较小的那个

原理:
证明1,该方法可以生成一棵树-》有一个最大值,共同头部
证明2. 生成的是二叉树而不是多叉树-》任何数在单独一侧,孩子的数量都不会超过一个
A1 …K1 …K2 A>K1 A>K2
设K1<k2<A, 选择较小的一个成为父节点, k2;A不可能为k1父节点
设K2<k1<A, 选择较小的一个 A不可能为k2父节点
总之,单独一侧不可能出现超过一个孩子
改进:利用栈快速得到每个数左右两边第一个比他大的数
3 1 2 求左边第一个大的数
3入栈,1比3小1入栈,1-》3
2比1大,1弹出,2比3小 2入栈,2-》3
3-》null
同理从右往左可求出右边第一个大的数表。

发布了11 篇原创文章 · 获赞 14 · 访问量 251

猜你喜欢

转载自blog.csdn.net/weixin_44303896/article/details/104004257