关于队列的一些题目

关于队列的一些题目

1、滑动窗口平均值

  • 描述:给定一个整数数据流和一个窗口大小,根据该滑动窗口的大小,计算滑动窗口里所有数字的平均值。
  • 解法:设置一个 sum,计算总和,在数值个数达到给定最大容量之前,一直添加,用 sum/que.size() 计算平均值。达到最大容量后,弹出最开始的那个,加入新的值,sum减去最开始的值,加上最后加入的值。sum/que.size() 计算平均值
  • 注意:sum 的类型用double,不然计算出来的值不会带小数
class MovingAverage {
    Queue<Integer> que;
    double sum = 0;
    int size = 0;
    /** Initialize your data structure here. */
    public MovingAverage(int size) {
        que = new LinkedList<Integer>();
        this.size = size;
    }

    public double next(int val) {
        if(que.size() == size){
            sum -= que.poll();  
        }   
            que.add(val);
            sum += val;
            return sum/que.size();
    }
}

2、最近请求次数

  • 描述:

    写一个 RecentCounter 类来计算特定时间范围内最近的请求。请实现 RecentCounter 类:RecentCounter() 初始化计数器,请求数为 0 。   int ping(int t) 在时间 t 添加一个新请求,其中 t 表示以毫秒为单位的某个时间,并返回过去 3000 毫秒内发生的所有请求数(包括新请求)。确切地说,返回在 [t-3000, t] 内发生的请求数。
    保证 每次对 ping 的调用都使用比之前更大的 t 值。
    
  • 解法:与上面近似,加入新值时要判断 前面的值和这个值之间的差值是否大于 3000,大于就要while 弹出

class RecentCounter {
    Queue<Integer> que;
    public RecentCounter() {
        que = new LinkedList<>();
    }
    
    public int ping(int t) {
        while(que.size()!=0 && (t-que.peek())>3000){
            que.poll();
        }
        que.add(t);
        return que.size();
    }
}

3、完全二叉树插入值

  • 描述:

    完全二叉树是每一层(除最后一层外)都是完全填充(即,节点数达到最大,第 n 层有 2n-1 个节点)的,并且所有的节点都尽可能地集中在左侧。
    
    设计一个用完全二叉树初始化的数据结构 CBTInserter,它支持以下几种操作:
    CBTInserter(TreeNode root) 使用根节点为 root 的给定树初始化该数据结构;
    CBTInserter.insert(int v)  向树中插入一个新节点,节点类型为 TreeNode,值为 v 。使树保持完全二叉树的状态,并返回插入的新节点的父节点的值;
    CBTInserter.get_root() 将返回树的根节点。
    
  • 解法:使用两个队列,普通队列用来遍历给定链表的节点,如果有空子节点的,就加入双端队列,先进去的编号最小,最接近 root 节点。双端队列用来给这些没孩子的加孩子。先要把这个新的节点加入到双端队列的尾部(他也莫得孩子),加孩子的顺序是:从最先进来双端队列的节点开始,先看左节点,如果左节点为空,就给这个节点的左孩子赋值,再看右节点,如果右节点为空,就给这个节点的右孩子赋值,赋值之后这个节点就左右孩子都有了,直接从双端队列里面删除。

class CBTInserter {
 TreeNode root;
    Deque<TreeNode> deque;
    public CBTInserter(TreeNode root) {
        this.root = root;
        deque = new LinkedList<>();
        Queue<TreeNode> que = new LinkedList<>();
        que.offer(root);
        while(!que.isEmpty()){
            TreeNode node = que.poll();
            if(node.left==null || node.right==null) deque.offerLast(node);
            if(node.left != null) que.offer(node.left);
            if(node.right != null) que.offer(node.right);
        }
    }
    
    public int insert(int val) {
        TreeNode node = deque.peekFirst();
        deque.offerLast(new TreeNode(val));
        if(node.left == null) node.left=deque.peekLast();
        else{
            node.right=deque.peekLast();
            deque.pollFirst();
        }
        return node.val;
    }
    
    public TreeNode get_root() {
        return root;
    }
}

4、二叉树每层的最大值

  • 描述:

    给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。
    
  • 解法:

    使用队列进行广度优先遍历,每一层都加入队列,对着一层的值寻找最大值,加入结果数组
    
  • 源码

    class Solution {
        public List<Integer> largestValues(TreeNode root) {
            if(root == null) return new ArrayList<Integer>();
            Queue<TreeNode> que = new LinkedList<>();
    
            List<Integer> res = new ArrayList<>(); 
            que.add(root);
            while(!que.isEmpty()){
                int queSize = que.size();
                int max = Integer.MIN_VALUE;
                while(queSize > 0){
                    TreeNode node = que.poll();
                    max = node.val>max ? node.val : max;
                    if(node.left != null) que.add(node.left);
                    if(node.right != null) que.add(node.right);
                    queSize--;
                }
                res.add(max);
            }
            return res;
        }
    }
    

5、二叉树最底层最左边的值

  • 描述:

    给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
    假设二叉树中至少有一个节点。
    
  • 解法:

    对左右两边都进行深度优先遍历,维护一个深度值与遍历的左右子树的深度值进行比较,保留更大的值
    
  • 源码:

    class Solution {
        public int findBottomLeftValue(TreeNode root) {
            dfs(root,1);
            return max.val;
        }
        int height = 0;
        TreeNode max = null;
        
        public void dfs(TreeNode root,int h){
            if(root == null) return;
            if(h > height){
                height = h;
                max = root;
            }
            dfs(root.left,h+1);
            dfs(root.right,h+1);
        }
    }
    

6、二叉树的右侧视图

  • 描述:

    给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
    
  • 解法:

    1、仍然可以使用 4 中的广度优先遍历,先判断左边,在判断右边。只不过将每一层的最后一个数据放到结果数组里面。刚好就是最右边的数据了。
    2、深度优先:对于每一个深度总是先访问右子树,那么每层访问到的第一个节点就是我们要的结果了
    
  • 源码:

    广度优先:
        class Solution {
    
        public List<Integer> rightSideView(TreeNode root) {
            List<Integer> res = new ArrayList<Integer>();
            if(root == null) return res;
            Queue<TreeNode> que = new LinkedList<>();
            que.add(root);
            while(!que.isEmpty()){
                int queSize = que.size();
                 while(queSize>0){
                     TreeNode node = que.poll();
                     queSize --;
                     if(queSize == 0) {
                        res.add(node.val);
                     }
                    if(node.left != null) que.add(node.left);
                    if(node.right != null) que.add(node.right);
                 }
            }
            return res;
        }
    }
        
        
    深度优先:
        
    class Solution {
        public List<Integer> rightSideView(TreeNode root) {
            Map<Integer, Integer> rightmostValueAtDepth = new HashMap<Integer, Integer>();
            int max_depth = -1;
    
            Deque<TreeNode> nodeStack = new ArrayDeque<TreeNode>();
            Deque<Integer> depthStack = new ArrayDeque<Integer>();
            nodeStack.push(root);
            depthStack.push(0);
    
            while (!nodeStack.isEmpty()) {
                TreeNode node = nodeStack.pop();
                int depth = depthStack.pop();
    
                if (node != null) {
                	// 维护二叉树的最大深度
                    max_depth = Math.max(max_depth, depth);
    
                    // 如果不存在对应深度的节点我们才插入
                    if (!rightmostValueAtDepth.containsKey(depth)) {
                        rightmostValueAtDepth.put(depth, node.val);
                    }
    
                    nodeStack.push(node.left);
                    nodeStack.push(node.right);
                    depthStack.push(depth + 1);
                    depthStack.push(depth + 1);
                }
            }
    
            List<Integer> rightView = new ArrayList<Integer>();
            for (int depth = 0; depth <= max_depth; depth++) {
                rightView.add(rightmostValueAtDepth.get(depth));
            }
    
            return rightView;
        }
    }
    
posted @ 2022-04-06 12:02  心是冰冰的  阅读(204)  评论(0)    收藏  举报