首页 > 其他分享 >经典数据结构题目-栈与队列

经典数据结构题目-栈与队列

时间:2024-01-21 22:48:33浏览次数:41  
标签:q1 题目 nums 队列 int new 数据结构 public

栈与队列

232. 用栈实现队列

  • 思路
    • 使用两个栈
    • 一个栈负责队列的push存元素,将里面的元素pop后放在另外一个栈。此时,另外一个栈最上面的就是最先放入,可用来做队列的pop
  • 代码
    public MyQueue() {
        pushSt = new Stack<>();
        popSt = new Stack<>();
    }
    
    public void push(int x) {
        pushSt.push(x);
    }
    
    public int pop() {
        if(popSt.isEmpty()){ // 注意点一
            while(!pushSt.isEmpty()){
                popSt.push(pushSt.pop());
            }
        }
        return popSt.pop();
    }

    public boolean empty() {
        return pushSt.isEmpty() && popSt.isEmpty();
    }
  • 注意点

    • 注意点一:只有负责pop的栈为空时,才需要从push的栈转移元素过来,这样才能保证pop栈最上面的元素是最先进入的
  • 扩展

    • Queue接口API

    • Deque接口API

    • StackAPI和Deque API对比

225. 用队列实现栈

  • 思路

    • 放入队列后,如果想找到最后插入的一个(后入先出),必现弹出之前插入的一批元素
    • 借助一个辅助队列,弹出前面插入的数据后,先放到另外一个队列中
    • 使用两个队列,始终有一个队列为空,用于弹出时做辅助
  • 代码

    public MyStack() {
        q1 = new LinkedList<>();
        q2 = new LinkedList<>();
    }
    
    public void push(int x) {
        // 放进非空的那一个q
        if(!q1.isEmpty()){
            q1.offer(x);
        }else{
            q2.offer(x);
        }
    }
    
    public int pop() {
        // 转移非空的那个q到空的那个,最后一个元素就是最后进入的
        Queue<Integer> emptyQueue = q1.isEmpty() ? q1 : q2;
        Queue<Integer> noEmptyQueue = q1.isEmpty() ? q2 : q1; 
        while(noEmptyQueue.size() > 1){
            emptyQueue.offer(noEmptyQueue.poll());
        }
        return noEmptyQueue.poll();
    }
    
    public int top() {
        Queue<Integer> emptyQueue = q1.isEmpty() ? q1 : q2;
        Queue<Integer> noEmptyQueue = q1.isEmpty() ? q2 : q1;
        int last = 0; 
        while(noEmptyQueue.size() > 0){
            last = noEmptyQueue.poll();
            emptyQueue.offer(last);
        }
        return last;
    }
    
  • 扩展

    • 一个队列也可以实现,循环使用。在poll之前记录下队列的长度n,poll后重新加入到队列,poll n次即可拿到最后的元素
     Queue<Integer> q;
    
        public MyStack() {
            q = new LinkedList<>();
        }
        
        public void push(int x) {
            q.add(x);
        }
        
        public int pop() {
            int size = q.size();
            while(size-- > 1){
                q.add(q.poll());
            }
            return q.poll();
        }
    

347. 前 K 个高频元素

  • 思路
    • 统计每个元素的次数,使用优先级队列进行排序。再弹出k个即可
  • 代码
    public int[] topKFrequent(int[] nums, int k) {
        // 统计次数
        Map<Integer,Integer> map = new HashMap<>();
        for(int num : nums){
            map.put(num,map.getOrDefault(num,0)+1);
        }
        // 使用优先级队列排序
        PriorityQueue<Map.Entry<Integer,Integer>> queue = 
            new PriorityQueue<>((o1,o2) -> o2.getValue()-o1.getValue());
        for(Map.Entry<Integer,Integer> entry : map.entrySet()){
            queue.offer(entry);
        }
        // 取出前k位
        int[] res = new int[k];
        while(k -- > 0){
            res[k] = queue.poll().getKey();
        }
        return res;
    }
  • 扩展
    • 优先级队列可以换成桶排序
    public int[] topKFrequent(int[] nums, int k) {
        // 统计次数
        Map<Integer,Integer> map = new HashMap<>();
        for(int num : nums){
            map.put(num,map.getOrDefault(num,0)+1);
        }
        // 用数组存储 index出现次数,value为
        List<Integer>[] frelists = new List[nums.length + 1];
        for(int key : map.keySet()){
            int i = map.get(key);
            if(frelists[i] == null){
                frelists[i] = new ArrayList();
            }
            frelists[i].add(key);
        }
        // 取出前k位
        int[] res = new int[k];
        while(k -- > 0){
            res[k] = queue.poll().getKey();
        }
        return res;
    }

239. 滑动窗口最大值

  • 思路
    • 遍历全部元素,借助队列来存取得前k个中的最大值(窗口内的最大值)。每次遍历需要处理以下
      • 更新队列。移除非窗口内的元素
      • 移除队列中小于当前元素的,添加当前元素。因为是向右移动的,比当前小的元素在之后的窗口里不可能成为最大值
      • 辅助队列会形成一个单调递减队列
      • 取辅助队列的第一个元素即为当前窗口最大值
  • 代码
	    public int[] maxSlidingWindow(int[] nums, int k) {
        int[] res = new int[nums.length - k + 1];
        // 辅助队列,第一个元素为窗口当前最大值
        Deque<Integer> dq = new LinkedList<>();

        // 考虑[i-k+1,i]的窗口
        for(int i = 0; i < nums.length; i++){

            // 更新队列,不在窗口内的元素进行移除
            if(!dq.isEmpty() && dq.peekFirst() < i - k + 1){
                dq.pollFirst();
            }

            // 可以移除掉小于当前值的数
            while(!dq.isEmpty() && nums[dq.peekLast()] < nums[i]){
                dq.pollLast();
            }
            dq.offerLast(i);
            
            // 填充最大值
            if(i >= k - 1){
                res[i-k+1] = nums[dq.peekFirst()];
            }
        }
        return res;

    }

标签:q1,题目,nums,队列,int,new,数据结构,public
From: https://www.cnblogs.com/gg12138/p/17978449

相关文章

  • 【OpenCV】:浅析 OpenCV 中的图像数据结构 Mat
    以下内容主要来自OpenCV中的mat.hpp这个头文件关于MatMat是OpenCV中用来存储图像数据的基础数据结构,原话是Itcanbeusedtostorerealorcomplex-valuedvectorsandmatrices,grayscaleorcolorimages,voxelvolumes,vectorfields,pointclouds,tensors,......
  • 数据结构
    时间复杂度评判规则:量化算法执行的操作/执行步骤的数量;最重要的项:时间复杂度表达式中最有意义的项大O记法:O(最重要的一项)O(1)表示一个特殊复杂度,含义为某个任务通过有限可数的资源即可完成,于输入数据量n无关;一个顺序结构的代码,时间负责度是O(1);二分查找法,分而治之的二分......
  • 用队列实现栈
      /**@lcapp=leetcode.cnid=225lang=cpp**[225]用队列实现栈*///@lccode=startclassMyStack{public:MyStack(){q1=newqueue<int>;q2=newqueue<int>;}~MyStack(){deleteq1;......
  • 用栈实现队列
      /**@lcapp=leetcode.cnid=232lang=cpp**[232]用栈实现队列*///@lccode=startclassMyQueue{public:MyQueue(){}voidpush(intx){s1.push(x);}intpop(){if(s2.empty()){......
  • 数据结构——栈及相关操作
    #include<bits/stdc++.h>#defineMaxSize10#defineElementTypeinttypedefstruct{ElementTypedata[MaxSize];inttop;}SqStack;voidInitStack(SqStack&S){S.top=-1;}boolStackEmpty(SqStack&S){if(S.top==-1)......
  • P1886 滑动窗口 /【模板】单调队列
    P1886滑动窗口/【模板】单调队列https://www.luogu.com.cn/problem/P1886 思路https://zhuanlan.zhihu.com/p/346354943 Codehttps://www.luogu.com.cn/record/143623041LLn,k;LLa[1000005];deque<LL>maxd,mind;intmain(){cin>>n>>k;......
  • 代码随想录算法训练营第十天| 232.用栈实现队列 225. 用队列实现栈
    LeetCode232.用栈实现队列题目链接:232.用栈实现队列思路:用两个栈实现队列 LeetCode  225.用队列实现栈 题目链接:225.用队列实现栈 思路:一个队列对栈进行实现(实现栈中的方法) ......
  • redis实现延时队列(附完整代码)
    最近在复习所学过的队列的知识,像什么LinkedBlockingDeque。ArrayBlockingQueue,还有ribbitmq里的乱七八糟的,其本质我感觉啊这些技术就是一些队列,只不过大体上分为单机队列和分布式队列而已,当然本文的重点在于redis实现延时队列啊,可能有人会说,用ribbitmq这个专门的消息中间件实现延时......
  • 【数据结构】详谈队列的顺序存储及C语言实现
    循环队列及其基本操作的C语言实现前言大家好,很高兴又和大家见面啦!!!在上一篇内容中,我们在介绍完队列的基本概念、重要术语以及基本操作后,又回顾了一下数据结构的三要素——数据的逻辑结构、数据的存储结构以及数据的运算。队列这种数据结构我们已经介绍了它的逻辑结构以及数据运算......
  • 最大异或和 可持久化数据结构入门
    最大异或和题目描述给定一个非负整数序列\(\{a\}\),初始长度为\(N\)。有\(M\)个操作,有以下两种操作类型:Ax:添加操作,表示在序列末尾添加一个数\(x\),序列的长度\(N\)加\(1\)。Qlrx:询问操作,你需要找到一个位置\(p\),满足\(l\lep\ler\),使得:\(a[p]\oplusa[p+1]......