关于队列的一些题目
关于队列的一些题目
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; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)